hdu3367并查集

来源:互联网 发布:办公软件基本知识 编辑:程序博客网 时间:2024/05/13 06:35
#include<stdio.h>#include<stdlib.h>#include<iostream>#include<string.h>using namespace std;#define N 1000int f[N],vis[N];struct node{       int a ,b,w;       friend bool operator <(const node &A,const node &B)       {return  A.w>B.w;}};node data[N];int find(int a){    int i=a;    while(f[i]!=i)    i=f[i];        int j=a,k;    while(f[j]!=i)    {        k=f[j];        f[j]=i;        j=k;    }    return i;}void union1(int a ,int b){     int fa=f[a];     int fb=f[b];     if(fa!=fb)     f[fa]=fb;}void init(int n){for(int i=1;i<=n;i++) f[i]=i;}int main(){    int i,j,n,m,ans;    while(scanf("%d%d",&n,&m))    {        if(!n&&!m)break;        ans=0;        memset(vis,0,sizeof(vis));        init(n);        for(i=1;i<=m;i++)            scanf("%d%d%d",&data[i].a,&data[i].b,&data[i].w);            sort(data+1,data+1+m);        for(i=1;i<=m;i++)        {            int a=find(data[i].a);            int b=find(data[i].b);            if(a!=b)//一开始肯定都是不在一颗树上的,连起来             {               if(vis[a]&&vis[b])continue;               if(vis[a]||vis[b])vis[a]=vis[b]=1;               union1(a,b);//无论怎样都连起来                ans+=data[i].w;            }             else if(!vis[a])//在同一棵树上却都没有环,才可以将两点连起来             {                 vis[a]=vis[b]=1;                 union1(a,b);                 ans+=data[i].w;            }//这里不用else,就是如果有环,丢掉         }        printf("%d\n",ans);    }    return 0;}/*3 30 1 11 2 12 0 14 50 1 11 2 12 3 13 0 10 2 20 0*/这道题的做法和克鲁斯卡尔算法过程上差不多,都是利用了并查集的性质合并的时候分三种情况:1是否两个都有环,2其中一个有环,3两个都没有环有位朋友说:不能直接求最大生成树,有待验证!判断树有没有环,用Vis数组,这个过程很典型!

原创粉丝点击