https://codeforces.com/problemset/problem/623/A
题意:给你一张图,给三个字母a,b,c。图的要求是如果字母相同或者相邻则必须连边,给你一张图,问能不能满足这个条件。满足则输出一种方案。
思路:比较明显的是完全图肯定是能满足的(大不了全a)
考虑到题目中有一个比较核心的连接点b,能连接a和c,所以说如果图里面有度数为n-1的点,那肯定是b,那么把相关的边去掉看剩下的图的情况。这个过程就是建立了一张补图。
然后补图上只有a和c两个字母,根据条件补图上两端点的字母需要不同,所以染色法判定一下二分图。判完之后最后对整张图check一下看看是否存在连线点两端的颜色>=2,存在就NO。否则输出染色的方案。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=600;
typedef long long LL;
vector<LL>g[maxn];//构建补图
LL ma[maxn][maxn],col[maxn],deg[maxn];
bool flag=1;
void dfs(LL u,LL color)//染色法判定二分图
{
col[u]=color;
for(LL i=0;i<g[u].size();i++){
LL v=g[u][i];
if(col[v]==col[u]){
flag=0;return;
}
if(!col[v]){
dfs(v,4-color);
}
}
}
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL n,m;cin>>n>>m;
for(LL i=1;i<=m;i++){
LL x,y;cin>>x>>y;ma[x][y]=ma[y][x]=1;
deg[x]++;deg[y]++;
}
for(LL i=1;i<=n;i++){
for(LL j=1;j<=n;j++){
if(i==j) continue;
if(!ma[i][j]) g[i].push_back(j),g[j].push_back(i);
}
}
for(LL i=1;i<=n;i++){
if(deg[i]==n-1) col[i]=2;//b点染色
}
for(LL i=1;i<=n;i++){
if(!col[i]){
dfs(i,1);//染a色
break;
}
}
if(flag==0) cout<<"NO"<<endl;
//check
else{
for(LL i=1;i<=n;i++){
for(LL j=1;j<=n;j++){
if(i==j)continue;
if(ma[i][j]&&abs(col[i]-col[j])>=2)
{
cout<<"NO"<<endl;return 0;
}
}
}
cout<<"YES"<<endl;
for(LL i=1;i<=n;i++){
if(col[i]==1) cout<<"a";
if(col[i]==2) cout<<"b";
if(col[i]==3) cout<<"c";
}
cout<<endl;
}
return 0;
}