poj 1679 The Unique MST (裸次小生成樹)

      step 1. 先用prim求出最小生成樹T.
           在prim的同時,用一個矩陣max[u][v] 記錄 在T中連結任意兩點u,v的唯一的
         路中權值最大的那條邊的權值. (注意這裏).
         這是很容易做到的,因爲prim是每次增加一個結點s, 而設已經標號了的結點
         集合爲W, 則W中所有的結點到s的路中的最大權值的邊就是當前加入的這條邊.
         step 1 用時 O(V^2).
     step 2.  枚舉所有不在T中的邊uv, 加入邊uv則必然替換權爲max[u][v]的邊。


The Unique MST
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 29427   Accepted: 10529

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!

code:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=510;
#define inf 0x3f3f3f3f
int n,E;
int vis[N],used[N][N],map[N][N],MAX[N][N],low[N],pre[N];
//used標記邊是否在最小生成樹中,MAX[i][j]存i-j在MST中的最大邊權
int prim()
{
    memset(vis,0,sizeof(vis));
    memset(used,0,sizeof(used));
    memset(pre,0,sizeof(pre));
    memset(MAX,0,sizeof(MAX));
    memset(low,0,sizeof(low));
    int p,minn,ans=0;
    vis[1]=1;
    p=1;
    for(int i=1;i<=n;i++)
    {
        low[i]=map[p][i];
        pre[i]=p;
    }
    for(int i=1;i<n;i++)
    {
        minn=inf;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&minn>low[j])
            {
                minn=low[j];
                p=j;
            }
        }
        ans+=minn;
        used[p][pre[p]]=used[pre[p]][p]=1;//標記,與MST的不同之處
        vis[p]=1;
        for(int j=1;j<=n;j++)
        {
            if(vis[j]) MAX[p][j]=MAX[j][p]=max(MAX[j][pre[p]],low[p]);//與MST的不同之處
            if(!vis[j]&&low[j]>map[p][j])
            {
                low[j]=map[p][j];
                pre[j]=p;//更新,與MST的不同之處
            }
        }
    }
    return ans;
}
int main()
{
    int T,x,y,z;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&E);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j) map[i][j]=0;
                else
                    map[i][j]=inf;
            }
        }
        while(E--)
        {
            scanf("%d%d%d",&x,&y,&z);
            if(map[x][y]>z)
            {
                map[x][y]=z;
            }
            if(map[y][x]>z)
            {
                map[y][x]=z;
            }
        }
     int result=prim();
        int flag=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                if(!used[i][j])
                {
                    if(map[i][j]==MAX[i][j])//尋找是否有不在MST中,但和MST中權值相同的邊
                    {
                           flag=1;break;
                    }
                }
            }
            if(flag) break;
        }
        if(flag) printf("Not Unique!\n");
        else
            printf("%d\n",result);
    }
}


發佈了70 篇原創文章 · 獲贊 25 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章