题目描述
当无线电台在一个非常大的区域上传播信号时,为了每个接收器都能得到较强信号,使用转发器转发信号。然而,需要仔细地选择每个转发器使用的频道,以使附近的转发器不彼此干扰。如果邻近的转发器使用不同的频道,条件就得到满足。
因为无线电波的频谱是宝贵的资源,转发器所需频道的数量应减到最少。编程任务:读取转发器网络的描述信息,并计算出所需频道的最小使用量。
输入
输入包含许多转发器网络图。每幅图的第一行是转发器数目(1~26)。转发器用连续的大写字母表示,从A开始。例如,10个转发器的名称分别是A,B,C,…,I和J。当转发器的个数是0时,表示输入结束。
转发器数目之后,是其邻近关系的列表。每行的格式为
A:BCDH
表示转发器B、C、D和H与转发器A邻近。第一行描述与转发器A邻近的,第二行描述与B邻近的,直到描述完所有的转发器。如果某个转发器不与其他转发器相邻,它的形式为
A:
转发器依字母顺序列出。
注意:相邻是对称的关系;如果A与B相邻,那么B与A也相邻。因为转发器位于水平面内,由相邻的转发器构成的网络图没有相交的线。
输出
对于每幅图(除了最后一个没有转发器),输出一行,是转发器不互相干扰所需的最少频道数。输出格式参考样例输出。注意:频道数为1的话,“channel”为单数。
样例输入
2
A:
B:
4
A:BC
B:ACD
C:ABD
D:BC
0
样例输出
1 channel needed.
3 channels needed.
思路分析
因为颜色不超过4种(根据四色原理,证明平面或球面上的任何地图的所有区域都至多可用四种颜色来着色,并使任何两个有一段公共边界的相邻区域没有相同的颜色。这个问题可转换成对一平面图的4着色判定问题),所以有如下两种情况:
所有的转发器互不相邻,只要着一种颜色;
用两种或三种颜色去着色,看看是否能够成功着色。如果都不能实现着色,那就是4种颜色。
代码实现
#include <iostream>
#include <string.h>
using namespace std;
int g[30][30]; //存储无向图
int used[30]; //已经使用的颜色
int n;
bool cha(int a,int color) //形参a是起始着色的结点,color是限制的着色数量
{
int flag; //着色成功的标志
for(int i=1;i<=color;i++){ //在规定的颜色数中着色
used[a]=i; //节点a使用第i号颜色
flag=1;
for(int j=1;j<a;j++){ //判断相邻节点是否使用了该颜色
if(g[a][j]==1&&used[j]==i){
flag=0;
break;
}
}
if(flag==1&&(a==n||cha(a+1,color))) return true;
//该颜色有效,当所有结点着色完毕返回true,或者给下一个结点着色
}
return false; //使用color个颜色没有实现全部着色
}
int main()
{
int i,j;
while(~scanf("%d",&n)){
if(n==0)break;
memset(g,0,sizeof(g));
memset(used,0,sizeof(used));
for(i=1;i<=n;i++){
char s[30];
cin>>s;
int len=strlen(s);
for(j=2;j<len;j++){ //从第3个字符起,是邻接关系结点
g[i][s[j]-'A'+1]=1; //对每个转发器的邻接关系,对称存储于数组g中即可。
g[s[j]-'A'+1][i]=1;
}
}
if(cha(1,1)){
cout<<"1 channel needed."<<endl;
}
else if(cha(1,2)){
cout<<"2 channels needed."<<endl;
}
else if(cha(1,3)){
cout<<"3 channels needed."<<endl;
}
else {
cout<<"4 channels needed."<<endl;
}
}
return 0;
}