【打卡】图着色问题

图着色算法是一类用于给图的顶点分配颜色,使得相邻顶点颜色不同的算法。常见的图着色算法有:

  • 贪心算法:按照一定的顺序依次给顶点着色,每次选择一个与相邻顶点颜色不同的最小可用颜色。贪心算法的时间复杂度较低,但不能保证得到最优解。
  • 回溯算法:通过递归的方式尝试所有可能的着色方案,当发现某个顶点无法着色时,回溯到上一个顶点,尝试其他颜色。回溯算法可以得到最优解,但时间复杂度较高,适用于小规模的图。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int maxn = 500 + 10;
  • #include<bits/stdc++.h>:这是一个非标准的头文件,它包含了 C++ 标准库中的几乎所有头文件,方便使用各种标准库函数和数据结构。
  • #define INF 0x3f3f3f3f:定义一个常量INF,其值为0x3f3f3f3f,通常用于表示无穷大。
  • typedef long long ll:将long long类型重命名为ll,方便后续使用。
  • using namespace std;:使用标准命名空间,这样就可以直接使用标准库中的类和函数,而无需加上std::前缀。
  • const int maxn = 500 + 10;:定义一个常量maxn,表示最大顶点数。
int v,e,k;
set<int> s;
int color[maxn];
vector<int> a[maxn];
  • v:表示图的顶点数。
  • e:表示图的边数。
  • k:表示可用的颜色数。
  • s:一个set容器,用于存储当前着色方案中使用的颜色集合。
  • color[maxn]:一个数组,用于存储每个顶点的颜色。
  • a[maxn]:一个邻接表,用于存储图的结构,a[i]存储与顶点i相邻的所有顶点。
int x,y,p;
scanf("%d%d%d",&v,&e,&k);
while(e--)
{
    scanf("%d%d",&x,&y);
    a[x].push_back(y);
    a[y].push_back(x);
}
  • scanf("%d%d%d",&v,&e,&k);:读取图的顶点数v、边数e和可用颜色数k
  • while(e--):循环e次,每次读取一条边的两个端点xy,并将它们添加到邻接表中,因为这是无向图,所以需要添加两条边。
scanf("%d",&p);
while(p--)
{
    s.clear();
    bool yes = true;
    memset(color,0,sizeof(color));
    for(int i = 1;i <= v;i++)
    {
        scanf("%d",&color[i]);
        s.insert(color[i]);
        int l = a[i].size();
        if(!yes) continue;
        for(int j =0;j < l;j++)
        {
            if(color[a[i][j]] == color[i] || s.size() > k)
            {
                yes = false;
                printf("No\n");
                break;
            }
        }
    }
    if(s.size() != k && yes)
    {
        printf("No\n");
        yes = false;
    }
    if(yes)
    {
        printf("Yes\n");
    }
}
return 0;
  • scanf("%d",&p);:读取着色方案的数量p
  • while(p--):循环p次,每次检查一个着色方案。
    • s.clear():清空颜色集合。
    • bool yes = true:初始化一个布尔变量yes,用于标记当前着色方案是否合法。
    • memset(color,0,sizeof(color));:将颜色数组初始化为 0。
    • for(int i = 1;i <= v;i++):遍历每个顶点。
      • scanf("%d",&color[i]);:读取当前顶点的颜色。
      • s.insert(color[i]);:将当前颜色插入到颜色集合中。
      • int l = a[i].size();:获取与当前顶点相邻的顶点数量。
      • if(!yes) continue;:如果已经确定当前着色方案不合法,则跳过后续检查。
      • for(int j =0;j < l;j++):遍历与当前顶点相邻的所有顶点。
        • if(color[a[i][j]] == color[i] || s.size() > k):如果相邻顶点的颜色与当前顶点相同,或者使用的颜色数超过了可用颜色数k,则标记当前着色方案不合法,并输出No
    • if(s.size() != k && yes):如果使用的颜色数不等于可用颜色数k,且之前判断为合法,则标记当前着色方案不合法,并输出No
    • if(yes):如果当前着色方案合法,则输出Yes

体会:

学习图着色算法,在思维层面,它极大地锻炼了我的逻辑思维。面对复杂的图结构,需严谨梳理顶点与边的关系,分析如何在相邻顶点不能同色的规则下巧妙着色,这个过程让我思考问题更加有条理。​从实际应用看,图着色算法在调度安排领域发挥巨大作用。这不仅提升了我的问题解决能力,更让我意识到算法在优化资源分配、提高工作效率方面的巨大能量。​

同时,学习过程中对贪心、回溯等算法策略的钻研,拓宽了我的算法知识储备,让我在面对其他编程难题时,能从更多角度去构思解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值