HDU 1272 并查集

来源:互联网 发布:ubuntu系统可以干什么 编辑:程序博客网 时间:2024/05/25 20:01

1.没有环

2.必须联通(有点类似“最小生成树”&…&)

1.创建集合(用树表示),每输入一对边就加入到集合中(成为树的子节点),如果输入的这条边两个定点都已经在同一集合中,说明出现了环

2.要满足题意:必须使 最后有且只有一个集合。说明所有的节点的根都是相同的。

并查集模版:

int p[maxn],r[maxn];void init(){for(int i=0;i<=maxn;i++) { p[i]=i;r[i]=0; }}int find(int x)//路径压缩{    if(x==p[x]) return x;    else return p[x]=find(p[x]);}int add(int x,int y)//按秩合并{    x=find(x); y=find(y);    if(x==y)    return -1;    if(r[x]>r[y])   p[y]=x;    else    {        p[x]=y;        if(r[x]==r[y])  r[y]++;    }    return 1;}
完整代码如下:

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;int p[100005];int r[100005];int c[100005];int find(int x){    if(x==p[x]) return x;    else return p[x]=find(p[x]);}int add(int x,int y){    x=find(x); y=find(y);    if(x==y)    return -1;    if(r[x]>r[y])   p[y]=x;    else    {        p[x]=y;        if(r[x]==r[y])  r[y]++;    }    return 1;}int main(){    int x,y;    bool fag;    while(~scanf("%d%d",&x,&y))    {        if(x==0 && y==0)        {            printf("Yes\n");            continue;        }        fag=true;        for(int i=0;i<=100000;i++) p[i]=i;        memset(r,0,sizeof(r));        if(x==-1 && y==-1) break;        p[x]=y; r[y]++;        c[0]=x;c[1]=y;        int k=2;        while(scanf("%d%d",&x,&y))        {            if(x==0 && y==0)                break;            c[k++]=x;               //这个地方其实可以去重,懒得去了            c[k++]=y;            if(add(x,y)==-1) fag=false;        }        if(!fag)   { printf("No\n"); continue;}        int f=find(c[0]);        for(int i=1;i<k;i++)        {            if(find(c[i]) != f)            {                fag=false;                break;            }        }        if(!fag)    printf("No\n");        else    printf("Yes\n");    }    return 0;}


0 0
原创粉丝点击