poj 1679 The Unique MST [Kurskal 最小生成樹是否唯一:次小生成樹]

The Unique MST

poj 1679題目鏈接

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 34429 Accepted: 12559

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!

Source

POJ Monthly–2004.06.27 srbga@POJ

解題思路

題意比較簡單,就是說最小生成樹是否唯一。也就是求次小生成樹,判斷是否有次小生成樹和最小生成樹的值相同。

這裏我用的Kurskal ,比較容易理解。次小生成樹,在最小生成樹的基礎上,加上一條邊,讓他構成一個環,然後在這個環裏面去掉一個最大的邊,剩下的樹就是次小生成樹了。不過要記得就是對每一條邊都要進行替換,看是否能找到相等的值的生成樹。

Kurskal 實現的話比 prime 更容易理解一點的,也更容易實現。因爲Kurskal 算法就是根據邊來找生成樹的。

程序代碼

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define inf 99999999
using namespace std;
int pur[110];

struct node{
    int u,v,l;
    int h;      //判斷邊是否用過 
};
node q[100010];
int cmp(node a,node b){
    return a.l<b.l;
}

int find(int x){
    if(pur[x]==x)
        return x;
    else
        pur[x]=find(pur[x]);
    return pur[x];
}

int merge(int u,int v){     //如果集合裏面沒有,就可以加進來 
    int t1=find(u);
    int t2=find(v);
    if(t1!=t2){
        pur[t1]=t2;
        return 1;
    }
    return 0;
}

int Kurskal(int n,int m,int v){     //求最小生成樹 
    int i,j,k;
    for(i=0;i<=n;i++)
        pur[i]=i;
    j=0; k=0;
    for(i=0;i<m;i++){
        if(q[i].l!=inf&&merge(q[i].u,q[i].v)){
            j++;
            k+=q[i].l;
            if(v==1)                //標記最小生成樹用過哪些邊 
                q[i].h=1;           //次小生成樹則不用進行標記 
        }
        if(j==n-1)
            break;
    }
    if(j==n-1)
        return k;
    return -1;
}

int main()
{
    int t,n,m,p;
    int i,j,k,ans,flag;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(i=0;i<m;i++){
            scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].l);
            q[i].h=0;
        }
        flag=0;
        sort(q,q+n,cmp);

        ans=Kurskal(n,m,1);     //這裏就是當前圖的最小生成樹 

        for(i=0;i<m;i++){       //這裏是求次小生成樹 
            if(!q[i].h)         //這條邊必須要用過 
                continue;
            p=q[i].l;

            q[i].l=inf;         //分別把每一條最小生成樹用過的邊都清除掉 

            k=Kurskal(n,m,0);   //然後再次尋找最小生成樹 

            q[i].l=p;           //清除掉的邊再變回來,循環清除下一條邊 

            if(k==ans){         //相等說明次小生成樹出現與最小生成樹相等的值 
                flag=1;
                break;
            }
        }
        if(flag)
            printf("Not Unique!\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章