7-30 图着色问题

题目如下:

7-30 图着色问题 (25 分)

图着色问题是一个著名的NP完全问题。给定无向图G=(V,E),问可否用K种颜色为V中的每一个顶点分配一种颜色,使得不会有两个相邻顶点具有同一种颜色?

但本题并不是要你解决这个着色问题,而是对给定的一种颜色分配,请你判断这是否是图着色问题的一个解。

输入格式:

输入在第一行给出3个整数V(0

输出格式:

对每种颜色分配方案,如果是图着色问题的一个解则输出Yes,否则输出No,每句占一行。

输入样例:

6 8 3
2 1
1 3
4 6
2 5
2 4
5 4
5 6
3 6
4
1 2 3 3 1 2
4 5 6 6 4 5
1 2 3 4 5 6
2 3 4 2 3 4

输出样例:

Yes
Yes
No
No

题目的关键字眼一般是特殊情况(测试点的 设定),或者是题目给定假设(避免自我增加题目难度,甚至无解)。当然对于题目未说明清楚的貌似模棱两可的字眼,自然属于后者(其常藏于常识之中):图着色问题是著名的NP完全问题,在这句话的基础上,将其进一步的说明简化就显得理直气壮了。简化的地方在于k种颜色的分配中,“分配”二字,那么,要不要全部分配呢,不全部分配算数吗,务必保留疑惑,可以假设,然后之多提交两次即可解决,从这里吸取最大的教训莫过于:读题有疑惑,务必保留。此外,还有一个疑惑,也就是一开始看不大懂的题意:顶点和颜色都从1到V编号,明明颜色只有K种,为什么也能标到V,一开始看了好几遍,后来才想通了的,只是标号,而k是种类。is函数比较直白,代码如下:

bool is()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i][j]&&v[i]==v[j])
			{
				return false;
			}
		}
	}
	return true;
}

主函数贵在获取数据的次序,先获取n,e,k;再根据边数获取存在边的两点(由于只需要判断是否相邻,把它当作有向图即可);为了统一,也为了更贴近题意,下标标志为1~V;获取t,用while(t--)获取着色方案,不用memset清零,会覆盖的,用set记录种数。主函数代码如下:

int main()
{
//	freopen("in.txt","r",stdin);
	scanf("%d%d%d",&n,&e,&k);
	int x,y;
	for(int i=0;is;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&v[i]);
			s.insert(v[i]);
		}
		if(s.size()==k&&is())
			cout<<"Yes\n";
		else
			cout<<"No\n";
	}
	return 0;
}

总代码如下:

#if 1 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include  
using namespace std;
const int N=505;
int a[N][N],v[N],n,e,k;
bool is()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i][j]&&v[i]==v[j])
			{
				return false;
			}
		}
	}
	return true;
}
int main()
{
//	freopen("in.txt","r",stdin);
	scanf("%d%d%d",&n,&e,&k);
	int x,y;
	for(int i=0;is;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&v[i]);
			s.insert(v[i]);
		}
		if(s.size()==k&&is())
			cout<<"Yes\n";
		else
			cout<<"No\n";
	}
	return 0;
}
#endif

 

你可能感兴趣的:(算法竞赛)