2019牛客暑期多校训练营(第六场)E 构造、原图是补图的同构图
https://ac.nowcoder.com/acm/contest/886#question
题意 问是否存在某个n个点的无向图G是其补图H的同构图,若存在输出G的邻接矩阵以及H关于G的映射。
解析 构造题,答案不唯一。原图与补图边数要一样,所以当n=4*k+2和4*k+3时无解
当n=4*k 时 将点分成4部分P1,P2,P3,P4 前两部分P1P2所有的点两两连边组成团,P3P1部分与部分之间两两连边,P4P2部分与部分之间两两连边
它的补图 是 P3P4组成团,P4P1之间连边,P3P2之间连边,与原图是同构的。
块之间映射关系,原图 P1P2P3P4 补图P3P4P2P1或其他方案。
当n=4*k+1时 剩下一个点随便和两个块连就好了。
代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e3+10; int g[maxn][maxn]; int main() { int t,n,kase=1; cin>>t; while(t--){ cin>>n; memset(g,0,sizeof(g)); printf("Case #%d: ",kase++); if(n%4==2||n%4==3){ cout<<"No"<<endl; continue; } else { cout<<"Yes"<<endl; int block=n/4; for(int i=1;i<=block;i++){ for(int j=block+1;j<=2*block;j++) g[i][j]=g[j][i]=1; for(int j=2*block+1;j<=3*block;j++) g[i][j]=g[j][i]=1; for(int j=i+1;j<=block;j++) g[i][j]=g[j][i]=1; } for(int i=block+1;i<=2*block;i++){ for(int j=3*block+1;j<=4*block;j++) g[i][j]=g[j][i]=1; for(int j=i+1;j<=2*block;j++) g[i][j]=g[j][i]=1; } if(n%4==1){ for(int i=1;i<=2*block;i++) g[i][n]=g[n][i]=1; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++) printf("%d",g[i][j]); printf("\n"); } for(int i=2*block+1;i<=4*block;i++) printf("%d ",i); for(int i=2*block;i>=1;i--) printf("%d ",i); printf("%d\n",n); } else{ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++) printf("%d",g[i][j]); printf("\n"); } for(int i=2*block+1;i<=4*block;i++) printf("%d ",i); for(int i=2*block;i>=1;i--) printf("%d%c",i,i==1?'\n':' '); } } } }