POJ 1679 (次小生成树)

来源:互联网 发布:白帽seo技术 编辑:程序博客网 时间:2024/05/21 06:32

我们都知道最小生成树,那么次小生成树就是:T0是任一棵异于T的生成树,通过变换T0 --> T1 --> T2 --> ... --> Tn (T)  变成最小生成树。所谓的变换是,每次把Ti中的某条边换成T中的一条边, 而且树T(i+1)的权小于等于Ti的权。取T0为任一棵次小生成树,T(n-1) 也就是次小生成树且跟T差一条边。



此博客有详解:http://www.cnblogs.com/hxsyl/p/3290832.html


这样的话,就很好办了,本题是问是否存在不唯一的最小生成树。意味着权值相同而某一条边不同。所我们把最小生成树的每一条边遍历,用其它边代替这条边。求得cMST,若和MST相同则说明不唯一。



注意:变量很多,定义的位置要好好思考。


#include<iostream>#include<cstdio>#include<algorithm>using namespace std;class Node{public:    int s,e,v;}edge[10005];int f[105],num[105];int a[105];int n,m;bool cmp(Node x,Node y){    return x.v < y.v;}int Find(int x){    if(f[x] == x)        return x;    else        f[x] = Find(f[x]);    return f[x];}int Union(int x,int y){    int a = Find(x);    int b = Find(y);    if(a == b)        return 0;    else if(num[a] >= num[b]){        f[b] = a;        num[a] += num[b];    }else {        f[a] = b;        num[b] += num[a];    }    return 1;}int kruskal(){    for(int i = 1;i <= n; i++){        f[i] = i;        num[i] = 1;        a[i] = 0;    }    sort(edge+1,edge+m+1,cmp);    int pos = 1;    int mst = 0;    for(int i = 1;i <= m; i++){        if(Union(edge[i].s,edge[i].e)){            a[pos++] = i;           //保存最小树的n-1个边            mst += edge[i].v;        }        if(pos == n)            break;    }    int cmst,temp = 0x3f3f3f3f;    for(int i = 1;i <= n - 1; i++){     //遍历n-1次        for(int j = 1;j <= n; j++){            num[j] = 1;            f[j] = j;        }        pos = 1;        cmst = 0;        for(int j = 1;j <= m; j++){            if(a[i] == j)                continue;            if(Union(edge[j].s,edge[j].e)){                cmst += edge[j].v;                pos++;            }            if(pos == n)                break;        }        if(pos == n && temp > cmst)            temp = cmst;    }    if(temp != mst)        return mst;    else        return -1;}int main(){//    freopen("in.txt","r",stdin);    int ncase;    cin>>ncase;    while(ncase--){        cin>>n>>m;        for(int i = 1;i <= m; i++)            cin>>edge[i].s>>edge[i].e>>edge[i].v;        int ans = kruskal();        if(ans != -1)       //注意要用负数            cout<<ans<<endl;        else            cout<<"Not Unique!"<<endl;    }    return 0;}




0 0
原创粉丝点击