1. 程式人生 > >POJ_1679_The Unique MST(次小生成樹模板)

POJ_1679_The Unique MST(次小生成樹模板)

div 題目 矩陣 gson direct style data connected include

The Unique MST
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 23942 Accepted: 8492

Description

Given a connected undirected graph, tell if its minimum spanning tree is unique.

Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V‘, E‘), with the following properties:
1. V‘ = V.
2. T is connected and acyclic.

Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E‘) of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E‘.

Input

The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.

Output

For each input, if the MST is unique, print the total cost of it, or otherwise print the string ‘Not Unique!‘.

Sample Input

2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2

Sample Output

3
Not Unique!


題意:問最小生成樹是否唯一。

分析:求次小生成樹,推斷次小生成樹和最小生成樹是否相等。留作模板。

次小生成樹的步驟:

(1)先用Prime求出最小生成樹T,在Prime的同一時候用一個矩陣max_edge[u][v]記錄在T中連接隨意兩點u,v的唯一路徑中權

值最大的那條邊的權值。註意這裏是非常easy做到的。由於Prime是每次添加一個節點t。而設已經標了號的節點集合為S,則S

中全部節點到t的路徑中最大權值的邊就是當前增加的這條邊。

(2)枚舉最小生成樹以外的邊,並刪除該邊所在環上權值最大的邊。

(3)取得的全部生成樹中權值最小的一棵即為所求。

算法的時間復雜度為O(n^2)。

題目鏈接:

id=1679">http://poj.org/problem?id=1679

代碼清單:

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<string>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

const int maxn = 100 + 5;
const int maxv = 10000 + 5;
const int max_dis = 1e9 + 5;

int T;
int n,m;
int a,b,c;
int MST,_MST;
bool vis[maxn];
int father[maxn];
int dist[maxn];
int graph[maxn][maxn];
bool used[maxn][maxn];
int max_edge[maxn][maxn];

void init(){
    memset(vis,false,sizeof(vis));
    memset(used,false,sizeof(used));
    memset(max_edge,-1,sizeof(max_edge));
    memset(graph,0x7f,sizeof(graph));
}

void input(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        scanf("%d%d%d",&a,&b,&c);
        graph[a][b]=graph[b][a]=c;
        used[a][b]=used[b][a]=true;
    }
}

int prim(){
    int ans=0;
    dist[1]=0;
    vis[1]=true;
    father[1]=-1;
    for(int i=2;i<=n;i++){
        father[i]=1;
        dist[i]=graph[1][i];
    }
    for(int i=1;i<n;i++){
        int v=-1;
        for(int j=1;j<=n;j++){
            if(!vis[j]&&(v==-1||dist[j]<dist[v])) v=j;
        }
        ans+=dist[v];
        vis[v]=true;
        used[father[v]][v]=used[v][father[v]]=false;
        for(int j=1;j<=n;j++){
            if(vis[j]){
                max_edge[v][j]=max_edge[j][v]=max(max_edge[father[v]][j],dist[v]);
            }
            else{
                if(graph[v][j]<dist[j]){
                    dist[j]=graph[v][j];
                    father[j]=v;
                }
            }
        }
    }return ans;
}

int second_prim(){
    int ans=max_dis;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(used[i][j]) ans=min(ans,MST+graph[i][j]-max_edge[i][j]);
    return ans;
}

void solve(){
    MST=prim();
    _MST=second_prim();
    if(MST==_MST) printf("Not Unique!\n");
    else printf("%d\n",MST);
}

int main(){
    scanf("%d",&T);
    while(T--){
        init();
        input();
        solve();
    }return 0;
}









POJ_1679_The Unique MST(次小生成樹模板)