POJ 1679 The Unique MST --Kruskal应用

这题可以用次小生成树解,这里用Kruskal算法来做。每条边除维护u,v,w外,还维护:

used:表示这条边是否加过 

eq:表示有没有与这条边相等的边

del:删除标记,以便删边之用

如果对于一个最小生成树的的边A,有一条与之权值相等的边B,则考虑把A删掉,再求一次最小生成树,看求出的总权值是否与前一个最小生成树的总权值相等。如果相等,则不唯一,如果找遍了这些权值相等的边都没找到,就说明唯一(注意每次不相等的话要把A重新加进来)。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 107

struct Edge
{
    int u,v,w;
    bool eq,del,used;
}edge[N*N];

int cmp(Edge ka,Edge kb)
{
    return ka.w < kb.w;
}

int fa[N],n,m,first;

int findset(int x)
{
    if(x != fa[x])
        fa[x] = findset(fa[x]);
    return fa[x];
}

int Kruskal()
{
    int i,j,k = 0;
    int sum = 0;
    for(i=1;i<=n;i++)
        fa[i] = i;
    for(i=1;i<=m;i++)
    {
        if(edge[i].del)
            continue;
        int u = edge[i].u;
        int v = edge[i].v;
        int fx = findset(u);
        int fy = findset(v);
        if(fx != fy)
        {
            sum += edge[i].w;
            fa[fx] = fy;
            if(first)
                edge[i].used = 1;
            k++;
        }
        if(k >= n-1)
            break;
    }
    return sum;
}

int main()
{
    int t,i,j,u,v,w;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            edge[i].u = u;
            edge[i].v = v;
            edge[i].w = w;
            edge[i].del = edge[i].used = edge[i].eq = 0;
        }
        for(i=1;i<=m;i++)
        {
            for(j=1;j<=m;j++)
            {
                if(i == j)
                    continue;
                if(edge[i].w == edge[j].w)
                    edge[i].eq = 1;
            }
        }
        sort(edge+1,edge+m+1,cmp);
        first = 1;
        int w1 = Kruskal();
        int w2;
        first = 0;
        for(i=1;i<=m;i++)
        {
            if(edge[i].used && edge[i].eq)
            {
                edge[i].del = 1;
                w2 = Kruskal();
                if(w1 == w2)
                {
                    puts("Not Unique!");
                    break;
                }
                edge[i].del = 0;
            }
        }
        if(i > m)
            printf("%d
",w1);
    }
    return 0;
}
View Code