第一次做constructive algorithm的题,要我们构造出来一个图使得它的连通分量有a个,补图的连通分量有b个。
关键在于想到一个性质是图和补图至少有一个图是连通图。(这个性质的想到可以通过看样例2,然后多画点图就想出来了)那我们就知道a和b肯定有一个是1,那我们构造另一个不是1的就可以了(因为一个联通分量个数不是1的补图的联通分量个数一定是1)。这样问题就变成了怎么构造一个图使得他有x个联通分量,这个就比较简单了,这个图有n个点,那就前x-1个点一个点就是一个连通分量,剩下的点是一个联通分量。
注意到n>4的话a和b都能为1,但n=2,3的情况a和b只能一个为1,n=1可以都为1。所以要特判
n>4且a和b都为1的情况,构造一条链就行了
1 #include<iostream> 2 using namespace std; 3 4 int n,a,b,count=1; 5 int edge[1005][1005]; 6 7 int main(){ 8 cin>>n>>a>>b; 9 if(a!=1 && b!=1){//补图和原图至少一个联通 10 cout<<"NO"; 11 return 0; 12 } 13 14 if(a!=1){//构造一个有a个联通分量的图 15 a--; 16 while(a--){ 17 for(int i=1;i<=n;i++) edge[count][i]=edge[i][count]=0;//这个点是一个联通分量 18 count++; 19 } 20 for(int i=count+1;i<=n;i++) edge[count][i]=edge[i][count]=1;//这个点跟剩下的点组成一个无环连通分量 21 cout<<"YES"<<endl; 22 for(int i=1;i<=n;i++){ 23 for(int j=1;j<=n;j++) cout<<edge[i][j]; 24 cout<<endl; 25 } 26 return 0; 27 } 28 if(b!=1){//构造一个有b个联通分量的图 29 b--; 30 while(b--){ 31 for(int i=1;i<=n;i++) edge[count][i]=edge[i][count]=0;//这个点是一个联通分量 32 count++; 33 } 34 for(int i=count+1;i<=n;i++) edge[count][i]=edge[i][count]=1;//这个点跟剩下的点组成一个无环连通分量 35 cout<<"YES"<<endl; 36 for(int i=1;i<=n;i++){ 37 for(int j=1;j<=n;j++) { 38 if( i==j ) cout<<0; 39 else cout<<!edge[i][j]; 40 } 41 cout<<endl; 42 } 43 return 0; 44 } 45 46 if(a==1 && b==1 && n>=4){ 47 int connect=1; 48 for(int i=2;i<=n;i++){ 49 edge[connect][i]=edge[i][connect]=1; 50 connect=i; 51 } 52 cout<<"YES"<<endl; 53 for(int i=1;i<=n;i++){ 54 for(int j=1;j<=n;j++) cout<<edge[i][j]; 55 cout<<endl; 56 } 57 return 0; 58 } 59 60 if(a==1 && b==1){ 61 if(n==1) cout<<"YES"<<endl<<0; 62 else cout<<"NO"; 63 } 64 return 0; 65 }