题目链接:
# https://blog.csdn.net/MIKASA3/article/details/52334480
一 解题思路
1 首先,构造图结构,获得当前节点,以及其邻接点
2 然后,设置各节点的初始颜色为0
3 依次对每个节点进行着色:
3.1 给当前节点从c=1开始着色,判断
3.1.1 如果当前节点与各邻接节点的颜色均不相同,说明所选的颜色可用,于是:1 设置当前节点的颜色为c,2 然后对下一个节点进行着色处理
3.1.2 如果当前节点与某邻接节点的颜色相同,则设置c=c+1,并重新判断该节点,直到更新后的颜色值c保证“当前节点与各邻接点的颜色均不相同”。
4 终止条件:对所有节点均着色完毕。# 如果完成了对所有节点的颜色着色,且该节点的颜色值不为初始值0,则结束。
5 因此,统计所使用的颜色的不同数值,即为最小着色数,即本题目的最小信道数目。
示意图:
二 代码实现
# POJ1129-Channel Allocation
# https://blog.csdn.net/MIKASA3/article/details/52334480
# 解题思想:
# A:BC
# B:ACD
# C:ABD
# D:BC
# 1 首先,构造图结构,获得当前节点,以及其邻接点
# 2 然后,设置各节点的初始颜色为0
# 3 依次对每个节点进行着色:
# 3.1 给当前节点从c=1开始着色,判断
# 3.1.1 如果当前节点与各邻接节点的颜色均不相同,说明所选的颜色可用,于是:1 设置当前节点的颜色为c,2 然后对一个节点进行着色处理
# 3.1.2 如果当前节点与某邻接节点的颜色相同,则设置c=c+1,并重新判断该节点,直到更新后的颜色值c保证“当前节点与各邻接点的颜色均不相同”。
# 4 终止条件:对所有节点均着色完毕。# 如果完成了对所有节点的颜色着色,且该节点的颜色值不为初始值0,则结束。
# 5 因此,统计所使用的颜色的不同数值,即为最小着色数,即本题目的最小信道数目。
import collections
class Solution:
def DFS(self,data_dict,color_dict):
self.d_dict = data_dict
self.c_dict = color_dict
self.LEN = len(self.d_dict)
# 依次对每个节点进行处理
self.Nodes = []
for i in self.d_dict.keys(): # 为了能够对键值实现list索引,因此将其转存
self.Nodes.append(i)
self.dfs(0)
valuse = self.c_dict.values()
return len(set(valuse)) # 统计不同颜色的个数
def dfs(self,index):
# 终止条件:# 如果完成了对所有节点的颜色着色,即i == self.LEN-1 且 该节点的颜色值不为初始值0,则返回
if index == self.LEN and self.c_dict[self.Nodes[self.LEN-1]] != 0:
return
# 对第index个节点进行处理
i = self.Nodes[index]
# 设置该节点i的颜色值+1开始处理(初始颜色值为0)
self.c_dict[i] = self.c_dict[i]+1
## 判断当前节点i的颜色与其各邻节点的颜色是否有冲突
# 首先,取出其邻接点
Neib_nodes = self.d_dict[i]
if len(Neib_nodes) == 0: # 如果无邻接点,则直接给该节点赋值当前颜色,并对下一个节点进行着色处理
# self.c_dict[i] = self.c_dict[i];
self.dfs(index+1)
return
else:
## 依次对各邻节点进行判断
Flag = True #设置标志位:不冲突时,Flag为True
for j in Neib_nodes:
if self.c_dict[i] == self.c_dict[j]: # 如果存在颜色冲突
Flag = False
if Flag == True: # 如果不冲突
# self.c_dict[i] = self.c_dict[i]; # 则赋值当前节点该颜色,
self.dfs(index + 1) # 并对下一个节点进行着色处理
return
else:
# 如果冲突,则仍然对当前节点进行Dfs处理,即1 颜色值+1;2 检查其邻接点;直到与所有邻接点的颜色不再冲突,然后再对下一个节点index+1进行dfs处理。
self.dfs(index)
return
# 将数据转化为数据字典和颜色字典
def data2dict(subData):
data_dict = collections.defaultdict(list)
color_dict = collections.defaultdict(list)
for i in subData: #提取每一个节点,并记录其邻接点
# 对每个元素进行拆分
length = len(i)
if length == 2: #长度为2,说明该节点无邻接点
data_dict[i[0]] = []
else:
temp = []
for j in range(2,length):
temp.append(i[j]) #依次存储冒号后的邻接点
data_dict[i[0]] = temp
# 给各节点赋值颜色初始值0
keys = data_dict.keys()
for i in keys:
color_dict[i] = 0
return data_dict,color_dict
## 迎接输入
data = []
data_size = []
while True:
# 当输入为0时,终止
n = int(input().strip())
if n == 0:
break
else:
data_size.append(n)
# 存储数据
temp = []
for i in range(n):
temp.append(input().strip())
data.append(temp)
# 打印出来看看
print(data)
# 接下来,进行算法处理,对节点进行着色处理:
# 共N组数据
N = len(data_size)
for i in range(N):
# 分别提取每组数据
subData = data[i]
# 将数据转化为数据字典和颜色字典
data_dict,color_dict = data2dict(subData)
# 进行dfs处理
test = Solution()
ans = test.DFS(data_dict,color_dict)
if ans == 1:
print(str(ans) + " channel needed.")
else:
print(str(ans) + " channels needed.")
输入:
2
A:
B:
4
A:BC
B:ACD
C:ABD
D:BC
4
A:BCD
B:ACD
C:ABD
D:ABC
0
输出:
1 channel needed.
3 channels needed.
4 channels needed.