poj1679

判断最小生成树是否唯一

感觉这个做法特别暴力:先求出MST然后,枚举上面的边,逐个去掉后再跑kruskal,如果得到相等的结果,则不唯一

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
 
struct node{
    int x, y, dis;
    int flag;
}a[10005];
 
int cmp(node x, node y){
    return x. dis < y. dis;
}
int father[105], n;
 
int kruskal(int num, int m){
    int ans = 0, cnt = 1;
    for(int i = 0; i < m; i ++){
        if(i == num)//除去这条边之后再求一次最小生成树
            continue;
        int s1 = father[a[i]. x];
        int s2 = father[a[i]. y];
        if(s1 != s2){
            ans += a[i]. dis;
            cnt ++;
            father[s2] = s1;
            for(int j = 0; j <= n; j ++)
                if(father[j] == s2)
                    father[j] = s1;
        }
    }
    if(cnt != n)
        return -1;
    else
        return ans;
}
 
int main(){
    int m, t, sum, ans, cnt;
    scanf("%d", &t);
    while(t --){
        scanf("%d %d", &n, &m);
        for(int i = 0; i <= n; i ++)
            father[i] = i;
        for(int i = 0; i < m; i ++){
            scanf("%d %d %d", &a[i]. x, &a[i]. y, &a[i]. dis);
            a[i].flag = 0;
        }
        sort(a, a + m, cmp);
        cnt = 1;
        ans = 0;
        for(int i = 0; i < m; i ++){
            int s1 = father[a[i]. x];
            int s2 = father[a[i]. y];
            if(s1 != s2){
                a[i]. flag = 1;
                ans += a[i]. dis;
                cnt ++;
                father[s2] = s1;
                for(int j = 0; j <= n; j ++)
                    if(father[j] == s2)
                        father[j] = s1;
            }
        }
        int flag = 0;
        for(int i = 0; i < m; i ++){//枚举所有原最小生成树上的边
            if(a[i]. flag == 0)
                continue;
            sum = 0;
            for(int j = 0; j <= n; j ++)//初始化
                father[j] = j;
            sum = kruskal(i, m);
            if(sum == ans){//与之前的最小生成树比较,如果相等,那么肯定不是唯一的
                flag = 1;
                break;
            }
        }
        if(flag)
            printf("Not Unique!\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

ps:附一个想法,以后再敲233

上面的做法不够优秀是因为它没有利用原图MST的结果。枚举每个点,将它和其余点连接,则会得到一个环,然后删掉这个环上另外的一条边,则得到的是最有可能成为MST的生成树,也就是说只要比较那两条边权值就可以了,相等,则不唯一

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/82427663