POJ 1129-Channel Allocation + Python(DFS)

题目链接:

# 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. 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值