cf#AIM Tech Round -C. Graph and String-贪心/ 二分图染色

http://codeforces.com/contest/624/problem/C


给一个图,要求还原出一个string,字符串只有abc三种字符。

一个字符x会和相同或者在字母表与之相邻的字母连边

即a和ab连,b和abc连,c和bc连

知道了这个后,b是和所有点相连的,度数为n-1

所有度数为n-1的点,都标记为b

然后我们随便找一个不是b的点X,我们标记为C

对于X 会和所有的B,C相连,因为B已经标记过了,那么我们遍历一遍X的所有邻接点,就可以把所有的C标记出来了

剩下的都标记为A


vis[i]=1 ---A
vis[i]=2 ---B
vis[i]=3 ---C

标记完所有点后,我们n^2验证一遍,

任意2个点如果 abs(vis[i]-vis[j]==2)   表明是a-c c-a这种边  需要满足 map[i][j]=0;
如果 abs(vis[i]-[j])<=1  就是其他边 需要满足map[i][j]=1;


枚举每一对点,如果不满足上述条件,no,全部判断完后。yes.



#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
#define ptf(ar1,ar2)  pr__int64f("%I64d:%I64d\n",ar1,ar2);
typedef __int64 ll;
const ll maxn = 131707+500;

int vis[505];
int cnt[505];
int tm[505][505];
int main()
{

	int i,n;
	int j,m;
	cin>>n>>m;
	int x,y;
	for (i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		tm[x][y]=tm[y][x]=1;
		cnt[x]++;
		cnt[y]++;
	}
	for (i=1;i<=n;i++)
	{
		if (cnt[i]==n-1)
			vis[i]=2;  //为b
	}
	int who=0;
	for (i=1;i<=n;i++)
	{
		if (vis[i]!=2)  {vis[i]=3;who=i;break;} // C
	}
	if (!who)
	{
		printf("Yes\n");
		for (i=1;i<=n;i++)
			printf("b");
		printf("\n");
		return 0;
	}

	for (i=1;i<=n;i++)
	{
		if (tm[who][i]&& vis[i]!=2)  //与C相连的只有b和C
			vis[i]=3;
	}
	for (i=1;i<=n;i++)
	{
		if (!vis[i])
			vis[i]=1;
	}
	//check
	for (i=1;i<=n;i++)
	{
		for (j=i+1;j<=n;j++)
		{
			if (abs(vis[i]-vis[j])==2) //a-c
			{
				if (tm[i][j]) {printf("No\n"); return 0  ;}
			}
			if (abs(vis[i]-vis[j])<=1)  //a-b  b-c  c-c a-a b-b
			{
				if (!tm[i][j]){printf("No\n");return  0 ;}
			}
		}
	}
	printf("Yes\n");
	for (i=1;i<=n;i++)
	{
		if (vis[i]==1) printf("a");
		else if (vis[i]==2) printf("b");
		else printf("c");
	}
	printf("\n");
	return 0 ;
}


你可能感兴趣的:(cf#AIM Tech Round -C. Graph and String-贪心/ 二分图染色)