某野生动物园划分了 N 个园区,引进了 K 种动物。现动物园的领导希望将引进的动物们布满所有园区,但相邻的两个园区不要放同种动物。当然他们也意识到这是一个 NP 完全问题,所以并不指望你能解决。动物园方设计了多种分配方案,想请你写个程序帮助他们判断一下,每个方案是否可行?
输入格式:
输入在第一行给出 3 个整数 N(0<N≤500)、R(≥0)和 K(0<K≤N),分别是园区个数、相邻关系数、以及动物种类数。园区和动物都从 1 到 N 编号。随后 R 行,每行给出一对相邻园区的编号,以空格分隔。之后给出一个正整数 M(≤20),是待检查的分配方案的个数。随后 M 行,每行顺次给出 N 个园区安置的动物种类(第 i 个数字表示第 i 个园区安置的动物),数字间以空格分隔。题目保证每一对相邻园区的编号不同,且没有重复给出的相邻关系。
输出格式:
对每种分配方案,如果任意相邻的两个园区都安置了不同种类的动物,则在一行中输出 Yes,否则输出 No。但如果方案中出现的动物种类数并不是 K 种,你应该说明 Error: Too many species.(种类过多)或者 Error: Too few species.(种类过少)。
输入样例:
6 8 3
2 1
1 3
4 6
2 5
2 4
5 4
5 6
3 6
5
1 2 3 3 1 2
1 2 3 4 5 6
4 5 6 6 4 5
2 3 4 2 3 4
2 2 2 2 2 2
输出样例:
Yes
Error: Too many species.
Yes
No
Error: Too few species.
思路:
没啥思路,简单的图论问题,遍历每个点,检查一下他的邻接点是否跟他的动物种类相同即可。这里有个技巧,题目虽然考察的是无向图,但是邻接表维护为有向图对问题的解决是没有影响的,可以思考一下对不对。
#include<bits/stdc++.h>
using namespace std;
const int N=505;
vector<int> v[N]; //邻接表
int spe[N]; //存储每个动物园的动物种类
int n,r,k,m;
bool sp[N]; //判断有哪些动物种类
void add_v(int x,int y){
v[x].push_back(y);
// v[y].push_back(x); 第二条无向边添加可以省略
}
bool flag(){
for(int i=0;i<=n;i++){ //遍历邻接表
for(int j=0;j<v[i].size();j++){
if(spe[v[i][j]]==spe[i]){ //相邻的动物种类相同
return 0; //返回0
}
}
}
return 1; //否则返回1
}
int main(){
cin>>n>>r>>k;
while(r--){
int a,b;
cin>>a>>b;
add_v(a,b);
}
/* for(int i=0;i<=n;i++){ //测试代码请忽略*****
for(int j=0;j<v[i].size();j++){
cout<<v[i][j]<<" ";
}
cout<<endl;
}*/
cin>>m;
while(m--){
//spe.clear();
memset(spe,0,sizeof spe);
memset(sp,0,sizeof sp);
for(int i=1;i<=n;i++){
int xx;
cin>>xx;
spe[i]=xx;
sp[xx]=1;
}
/* for(int i=1;i<=n;i++){ 测试代码请忽略
cout<<i<<' '<<sp[i]<<' ';
}
cout<<endl;*/
int cnt=0;
for(int i=1;i<=n;i++){
if(sp[i]){ //如果此动物种类存在则cnt+1
cnt++;
}
}
if(cnt>k){ //种类大于k
cout<<"Error: Too many species."<<endl;
}else if(cnt<k){//小于k
cout<<"Error: Too few species."<<endl;
}else{
if(flag()){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
}
}
return 0;
}
有一个细节要注意,n,k的取值范围都是大于0小于等于n的,计数要从1开始。
还有千万不要忘记每次循环的memset()。