图着色算法是一类用于给图的顶点分配颜色,使得相邻顶点颜色不同的算法。常见的图着色算法有:
- 贪心算法:按照一定的顺序依次给顶点着色,每次选择一个与相邻顶点颜色不同的最小可用颜色。贪心算法的时间复杂度较低,但不能保证得到最优解。
- 回溯算法:通过递归的方式尝试所有可能的着色方案,当发现某个顶点无法着色时,回溯到上一个顶点,尝试其他颜色。回溯算法可以得到最优解,但时间复杂度较高,适用于小规模的图。
#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
次,每次读取一条边的两个端点x
和y
,并将它们添加到邻接表中,因为这是无向图,所以需要添加两条边。
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
。
体会:
学习图着色算法,在思维层面,它极大地锻炼了我的逻辑思维。面对复杂的图结构,需严谨梳理顶点与边的关系,分析如何在相邻顶点不能同色的规则下巧妙着色,这个过程让我思考问题更加有条理。从实际应用看,图着色算法在调度安排领域发挥巨大作用。这不仅提升了我的问题解决能力,更让我意识到算法在优化资源分配、提高工作效率方面的巨大能量。
同时,学习过程中对贪心、回溯等算法策略的钻研,拓宽了我的算法知识储备,让我在面对其他编程难题时,能从更多角度去构思解决方案。