题目链接:点击打开链接
题目大意:
现在有一些卡片,卡片的每一面有一个数字,判断是否能否把所有的卡片摆在桌子上,满足:任意一个任意一个数字出现次数不超过一次(任何数字不能两次朝上)。
解题思路:
一:把每个数字看成一个点,卡片上的数字间连接一条边,那么当某些数字能连成一个环时,这些数字必须每个都要出现一次(仔细想想),既然这样,那么这个环上面的数字就不能再参与其余环的形成,也不能与其余环相连(再仔细想想),那么我们把所有边建好后,就是判断图中是否有相连的环,有的话就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;
}