HDU-3367最大生成树

来源:互联网 发布:颧弓宽怎么办知乎 编辑:程序博客网 时间:2024/06/18 07:53

题目链接


http://acm.hdu.edu.cn/showproblem.php?pid=3367
 不能直接跑最大生成树,但是还可以存在一个环,这样一下就用krusal判环来写了就是比普通的最大生成树多了合并判断。
 代码来源于网络

#include<stdio.h>#include<iostream>#include<algorithm>using namespace std;typedef struct nn{    int x,y,p;}Node;Node edg[100005];int fath[10005],sum,cycle[10005];//cycle[]标记树有没有环int cmp(Node a,Node b)//用于sort排序时的标准{    return a.p>b.p;//从大到小排}void set_first(int n)//设制初始化{    for(int i=0;i<n;i++)    {        fath[i]=i; cycle[i]=0;    }}int find_fath(int x)//找根节点时,路径压缩{    if(x!=fath[x])    fath[x]=find_fath(fath[x]);    return fath[x];}void kruskal(int n,int m)//n为点数,m为边数{    int a,b,k=0;    sum=0;    set_first(n);//初始化    sort(edg,edg+m,cmp);//从大到小排序    for(int i=0;i<m;i++)    {        a=find_fath(edg[i].x);        b=find_fath(edg[i].y);        if(a!=b&&(cycle[a]!=1||cycle[b]!=1))//如果这两棵树都有环,那么不能合并        {            sum+=edg[i].p;            fath[a]=b;            if(cycle[a]) cycle[b]=cycle[a];//当合并时,注意环的标记是要相传的        }        else if(cycle[a]==0)//当两个点都在一棵树上并且树还没有环时,这棵树添一个边构成环        {           sum+=edg[i].p; cycle[a]=1;//并且标记这棵树有环,1表示有环        }    }}int main(){    int n,m;    while(scanf("%d%d",&n,&m)>0&&n+m!=0)    {        for(int i=0;i<m;i++)        scanf("%d%d%d",&edg[i].x,&edg[i].y,&edg[i].p);        kruskal(n,m);        printf("%d\n",sum);    }}