poj1679The Unique MST

来源:互联网 发布:淘宝卖家遇到的骗局 编辑:程序博客网 时间:2024/05/22 09:49

题目请戳这里

题目大意:判断最小生成树是否唯一

题目分析:求次小生成树,判断与最小生成树权值是否相等。

如何求次小生成树:先将出现权值相同的边标记,跑一次Kruscal,求出mst,并记录选出来的边,在选出来的边中任选一条被相同权值标记过的边,删掉,再求mst,记录最小值。

trick:删边Kruscal的时候,注意判断图不连通,因为如果删掉的是一条关键边,导致图不连通,求出的新生成树会少一条边,但是权值可能会和最小生成树相同。

详情请见代码:

#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N = 104;const int M = 100004;struct node{    int u,v,val;    bool sameval;}edge[M];int set[N];bool flag[M];int stack[N];int ans;int m,n;int cmp(struct node a,struct node b){    return a.val < b.val;}int find(int x){    if(set[x] != x)        set[x] = find(set[x]);    return set[x];}void Union(int a,int b){    int ra = find(a);    int rb = find(b);    set[ra] = rb;}bool Kruscal(){    int i,j,k,a,b;    for(i = 1;i <= n;i ++)        set[i] = i;    i = j = ans = 0;    while(i < m && j < n - 1)    {        a = find(edge[i].u);        b = find(edge[i].v);        if(a != b)        {            Union(edge[i].u,edge[i].v);            ans += edge[i].val;            stack[j ++] = i;        }        i ++;    }    for(i = 0;i < n - 1;i ++)        if(edge[stack[i]].sameval == true)            break;    if(i == n - 1)        return true;    memset(flag,false,sizeof(flag));    int sum;    for(i = 0;i < n - 1;i ++)    {        if(edge[stack[i]].sameval == true)        {            flag[stack[i]] = true;            sum = 0;            for(j = 1;j <= n;j ++)                set[j] = j;            j = k = 0;            while(j < m && k < n - 1)            {                if(flag[j] == true)                {                    j ++;                    continue;                }                a = find(edge[j].u);                b = find(edge[j].v);                if(a != b)                {                    Union(edge[j].u,edge[j].v);                    sum += edge[j].val;                    k ++;                }                j ++;            }            if(k != n - 1)                continue;            if(sum == ans)                return false;            flag[stack[i]] = false;        }    }    return true;}int main(){    int i,t;    scanf("%d",&t);    while(t --)    {        scanf("%d%d",&n,&m);        for(i = 0;i < m;i ++)        {            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].val);            edge[i].sameval = false;        }        if(n == 1)        {            printf("0\n");            continue;        }        sort(edge,edge + m,cmp);        for(i = 1;i < m;i ++)            if(edge[i].val == edge[i - 1].val)            {                edge[i - 1].sameval = true;                edge[i].sameval = true;            }        memset(flag,false,sizeof(flag));        if(Kruscal())            printf("%d\n",ans);        else            puts("Not Unique!");    }    return 0;}//880K0MS/*73 31 2 12 3 23 1 34 41 2 22 3 23 4 24 1 27 101 2 281 4 221 6 102 3 162 7 143 4 124 5 224 7 185 6 255 7 247 121 2 61 6 61 7 62 3 22 7 33 4 33 7 24 5 14 7 45 6 85 7 36 7 73 31 2 22 3 33 1 33 31 2 32 3 23 1 33 21 2 22 3 2*/