题意:给你两个图,问你这两个图的结构是否一样,此图的特点:每一个块,只有两种情况,一个环或是一个链。
想法:并查集处理每一个边,有环标记祖先,然后比较。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int nodes=10000+5; int n,m; int nn,mm; int flag; struct node { int rank,father,cir; }e1[nodes],e2[nodes]; bool cmp(node a,node b) { if(a.rank==b.rank) return a.cir<b.cir; else return a.rank<b.rank; } int find(int x,node *e) { if(x!=e[x].father) e[x].father=find(e[x].father,e); return e[x].father; } void union_set(int a,int b,node *e) { int ra=find(a,e); int rb=find(b,e); if(ra==rb) { e[ra].cir=1; return; } if(e[rb].rank>=e[ra].rank) { e[ra].father=rb; e[rb].rank+=e[ra].rank; } else { e[rb].father=ra; e[ra].rank+=e[rb].rank; } } void Input() { flag=1; for(int i=1;i<=n;i++) { e1[i].father=i; e2[i].father=i; e1[i].rank=1; e2[i].rank=1; e1[i].cir=0; e2[i].cir=0; } scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); union_set(a,b,e1); } scanf("%d%d",&nn,&mm); if(mm!=m) flag=0; for(int i=1;i<=mm;i++) { int a,b; scanf("%d%d",&a,&b); if(!flag) continue; union_set(a,b,e2); } } void treatment(int ca) { printf("Case #%d: ",ca); if(!flag) { printf("NO\n"); return; } sort(e1+1,e1+1+n,cmp); sort(e2+1,e2+n+1,cmp); for(int i=1;i<=n;i++) { if(e1[i].rank!=e2[i].rank||e1[i].cir!=e2[i].cir) { printf("NO\n"); return; } } printf("YES\n"); } int main() { int t,ca=1; scanf("%d",&t); while(t--) { Input(); treatment(ca++); } return 0; }