Hand in Hand(并查集)
题意:判断两个图形是否相似,根据题意可以知道图形的分量,不是环就是链,所以我们只要依次两个图形是否一样就可以了
分析:若两个图形完全一样的话,那么它们成环和成链的个数必定一样,当然成环(链)的点的个数也是一样的,所以我们可以忽视结点的本身,
而值注重这个点代表的意义就可以。一样的两图排序后,自然会有对等的点和对等相同意义的点
#include<stdio.h> #include<algorithm> using namespace std; const int MAXN=10010; int n1,n2,m1,m2; int father1[MAXN],father2[MAXN]; struct Graph { int son; bool ring; }gra1[MAXN],gra2[MAXN]; void Make_set(int n,int father[],Graph gra[]) { for(int i=1;i<MAXN;i++) { father[i]=i; gra[i].son=1; gra[i].ring=false;//初始化为链 } } int Find(int x,int father[]) { int r=x; while(r!=father[r]) { r=father[r]; } if(r!=x) father[x]=r; return r; } void Union(int x,int y,Graph gra[],int father[])//这里直接用x,y避免错误 { x=Find(x,father); y=Find(y,father); if(x==y)//这里注意必须注意是父节点,避免错误把a,b都省略 { gra[x].ring=true; return ; } else { if(gra[x].son>=gra[y].son) { gra[x].son+=gra[y].son; father[y]=x; } else { gra[y].son+=gra[x].son; father[x]=y; } } } bool cmp(Graph a,Graph b) { if(a.son<b.son) return true; else if(a.son==b.son && a.ring<b.ring) return true;//这里只写<是错的,没有=的话存在>的情况 return false; } bool _Judge(Graph g1[],Graph g2[],int num) { sort(g1+1,g1+n1+1,cmp); sort(g2+1,g2+n2+1,cmp); for(int i=1;i<=num;i++) { //printf("%d %d %d %d\n",g1[i].son,g2[i].son,g1[i].ring,g2[i].ring); if(g1[i].son!=g2[i].son || (g1[i].son==g2[i].son && g1[i].ring!=g2[i].ring)) return false; } return true; } int main() { int T,i,a,b; int cas=1; int flag; scanf("%d",&T); while(T--) { flag=true; scanf("%d%d",&n1,&m1); Make_set(n1,father1,gra1); for(i=0;i<m1;i++) { scanf("%d%d",&a,&b); Union(a,b,gra1,father1); } scanf("%d%d",&n2,&m2); Make_set(n2,father2,gra2); if(n1!=n2) flag=false; for(i=0;i<m2;i++) { scanf("%d%d",&a,&b); if(flag==false) continue; Union(a,b,gra2,father2); } flag=_Judge(gra1,gra2,n1); if(flag==false) printf("Case #%d: NO\n",cas++); else printf("Case #%d: YES\n",cas++); } }