弦图与完美消除序列(bzoj 1006: [HNOI2008]神奇的国度)

本文介绍了弦图的基本概念及特性,并详细阐述了利用完美消除序列解决弦图染色问题的方法,包括MCS算法的具体实现步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

诱导子图:子图中任意一条边的两个端点一定也都在这个子图中

最大团:团中任意两点之间一定都有边,而包含顶点最多的团就是最大团

最小团覆盖:用最少的团覆盖图中所有的点

最大独立集:独立集中任意两点之间一定都没有边,而包含顶点最多的独立集就是最大独立集

最小染色:用最少的颜色给图染色使得图中任意相邻的两点颜色不相同

弦图:无向图中任意长度大于3的环都至少有一个弦,所谓弦就是连接环中不相邻两点的边

一般来讲:

①最大团数<=最小染色数

②最大独立集<=最小团覆盖

对于弦图来讲:

①最大团数==最小染色数

②最大独立集==最小团覆盖

单纯点:如果与顶点V相邻的所有点能构成一个团,那么V就是个单纯点

③任何一个弦图都有至少一个单纯点,不是完全图的弦图至少有两个不相邻的单纯点

完美消除序列:一个点的序列(每个点刚好出现1次)v1, v2,…,vn满足vi在诱导子图{vi, vi+1,…,vn}中为一个单纯点

④一个无向图是弦图的充要条件是存在完美消除序列

参考文献:https://wenku.baidu.com/view/陈丹琦.html


1006: [HNOI2008]神奇的国度

Time Limit: 20 Sec   Memory Limit: 162 MB
Submit: 3762   Solved: 1725
[ Submit][ Status][ Discuss]

Description

  K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2...An之间仅存在N对认识关系:(A1A2)(A2A3)...(AnA1),而没有其它认识关系.比如四边关系指ABCD四个人 AB,BC,CD,DA相互认识,而AC,BD不认识.全民比赛时,为了防止做弊,规定任意一对相互认识的人不得在一队,国王相知道,最少可以分多少支队。

Input

  第一行两个整数N,M。1<=N<=10000,1<=M<=1000000.表示有N个人,M对认识关系. 接下来M行每行输入一对朋友

Output

  输出一个整数,最少可以分多少队

Sample Input

4 5
1 2
1 4
2 4
2 3
3 4

Sample Output

3

题目可以翻译为:用最少的颜色给弦图染色使得任意相邻的两点颜色不相同,即求最大团数

方法:求出完美消除序列然后暴力染色

可以使用MCS算法:

①从n到1的顺序依次给每个点标号

②lab[i]表示已经标号的点中有多少个与i相连,每次选择最大的lab[]进行标号

SA[i] = k表示标号为i的点是第k个点

然后就可以开始染色了,无脑从标号高的点开始染色即可


附录:如何判断是不是弦图?

求出完美消除序列然后看这个是不是完美消除序列(完美消除序列是否存在?)

判断方法:设{vi+1,vi+2,…,vn}中所有与vi相连的点依次为vj1, vj2,…

只需要判定vj1是否与vj2, vj3,…相邻即可

#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
int n, m, label[10005], R[10005], SA[10005];
vector<int> G[10005];
priority_queue<pair<int, int> > q;
void Color(int u) 
{
	int i, v;
	for(i=0;i<G[u].size();i++)
	{
		v = G[u][i];
		if(label[v]==-1)
			continue;
		R[label[v]] = u;
	}
	for(i=1;label[u]==-1;i++)
	{
		if(R[i]!=u)
			label[u] = i;
	}
}
int main(void)
{
	int i, u, v, id, now, ans;
	while(scanf("%d%d", &n, &m)!=EOF)
	{
		while(q.empty()==0)
			q.pop();
		for(i=1;i<=n;i++)
			G[i].clear();
		while(m--)
		{
			scanf("%d%d", &u, &v);
			G[u].push_back(v);
			G[v].push_back(u);
		}
		memset(R, -1, sizeof(R));
		memset(label, 0, sizeof(label));
		for(i=1;i<=n;i++)
			q.push(make_pair(0, i));
		for(id=n;id>=1;)
		{
			now = q.top().second;
			q.pop();
			if(R[now]!=-1)
				continue;
			SA[id] = now;
			R[now] = id--;
			for(i=0;i<G[now].size();i++)
			{
				u = G[now][i];
				if(R[u]!=-1) 
					continue;
				label[u]++;
				q.push(make_pair(label[u], u));
			}
		}
		memset(R, -1, sizeof(R));
		memset(label, -1, sizeof(label));
		for(i=n;i>=1;i--)
			Color(SA[i]);
		ans = 0;
		for(i=1;i<=n;i++)
			ans = max(ans, label[i]);
		printf("%d\n", ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值