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\n",w1);

    }

    return 0;

}
View Code

 

你可能感兴趣的:(unique)