题意:给出n,a,b,问,是否有这样的一个图,有n个节点,分成a块,现将两两节点之间有边的把边删除,两两节点之间无边的建边,使得形成的图分成b块。如果有,输出YES,并且输出这个图的邻接矩阵,否则输出NO。这题难就难在是否能推出结论以及答案的输出。
思路:任何一个图,不管分成多少块,经过上述操作后,必然变成一个联通图。
证:有n个节点,分成m块,任取一块,经过上述操作后,所取的这一块内的任意节点必定与其他块的所有节点相连!
这个结论换句话说就是,a和b里面,至少有一个数是1!知道这个结论就简单了,首先排除所有不含1的情况,然后,b==1的情况,我们将图分成a块,直接另前a-1块都只有一个节点,最后1块包含剩下的节点就行了。当然,对于a==1,只要将要输出反过来一下就可以了(注意,这里要讨论一下a和b都为1的情况,当n==2和n==3时,是不行的直接排除,其他情况都是可行的,特殊处理一下a和b都等于1的输出)我的输出比较繁琐,写完之后,看了一下大佬的输出方法,然后突然发现自己好菜啊QAQ。附上我的写法和大佬的写法(思路是一样的,输出不同)。
菜鸡的写法
#include "iostream"
#include "algorithm"
using namespace std;
const int Max=1e3+10;
int n,a,b,G[Max][Max],vis[Max];
char ch1='1',ch2='0';
int main() {
cin>>n>>a>>b;
if (a!=1&&b!=1||a==1&&b==1&&n<=3&&n>=2||a>n||b>n){
cout<<"NO"<<endl;
return 0;
}
cout<<"YES"<<endl;
if(a==1&&b==1){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j) cout<<"0";
else{
if(j==i-1||j==i+1) cout<<ch1;
else cout<<ch2;
}
}
cout<<endl;
}
}
else{
if(a==1&&b!=1) swap(a,b),swap(ch1,ch2);
for(int i=1,t=i;i<=a-1;i++){
for(int j=1;j<=n;j++)
if(i==j) cout<<"0";
else cout<<ch2;
cout<<endl;
}
for(int i=a;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j) cout<<"0";
else if(j>=a) cout<<ch1;
else cout<<ch2;
}
cout<<endl;
}
}
}
大佬的写法
#include "iostream"
#include "algorithm"
using namespace std;
int n,a,b;
char ch1='0',ch2='1';
int main() {
cin>>n>>a>>b;
if (a!=1&&b!=1||a==1&&b==1&&n<=3&&n>=2||a>n||b>n) {cout<<"NO"<<endl; return 0;}
cout<<"YES"<<endl;
if (a==1) swap(a,b), swap(ch1,ch2);
for (int i=0;i<n;i++) {
for (int j=0;j<n;j++) {
cout<<(i==j?'0':(i+1==j&&j>=a||j+1==i&&i>=a?ch1:ch2));
}
cout<<endl;
}
}