UVALive-7385-FlippingCards(并查集判环)

来源:互联网 发布:netstat -ano linux 编辑:程序博客网 时间:2024/06/06 01:57

题目链接:点击打开链接

题目大意:
现在有一些卡片,卡片的每一面有一个数字,判断是否能否把所有的卡片摆在桌子上,满足:任意一个任意一个数字出现次数不超过一次(任何数字不能两次朝上)。
解题思路:
一:把每个数字看成一个点,卡片上的数字间连接一条边,那么当某些数字能连成一个环时,这些数字必须每个都要出现一次(仔细想想),既然这样,那么这个环上面的数字就不能再参与其余环的形成,也不能与其余环相连(再仔细想想),那么我们把所有边建好后,就是判断图中是否有相连的环,有的话就impossible。
二:开始想到并查集,但是没想到可以用来判断环的个数快哭了: 只需要开一个数组记录,每个父结点的参与成环的个数,合并的时候,把两个父节点的值相加就好了。
三:当然也可以DFS()遍历,不过相比并查集就慢多了。
代码:
#include<iostream>#include<cstring>#include<string>#include<cstdio>#include<algorithm>using namespace std;const int maxn=5e4+10;int p[maxn<<1],cnt[maxn<<1];int FIND(int x){return p[x]==x?x:p[x]=FIND(p[x]);}int main(){    int T,n,u,v,x,y;    scanf("%d",&T);    while(T--){        scanf("%d",&n);        for(int i=0;i<=2*n;i++)p[i]=i;        memset(cnt,0,sizeof cnt);        for(int i=0;i<n;i++){            scanf("%d%d",&u,&v);            x=FIND(u);            y=FIND(v);            if(x==y)cnt[x]++;            else {p[x]=y;cnt[y]+=cnt[x];}        }        int is_ok=1;        for(int i=0;i<=2*n;i++){            if(cnt[i]>1){is_ok=0;break;}        }        if(is_ok)printf("possible\n");        else printf("impossible\n");    }    return 0;}


原创粉丝点击