最大势算法(HNOI2008 神奇的国度)(集合内不同色最少色染色问题)

链接:https://ac.nowcoder.com/acm/problem/20068
前置知识点:https://wenku.baidu.com/view/07f4be196c175f0e7cd13784.html(cdq 弦图与区间图)

题目描述

K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA 相互认识,是简洁高效的.

为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2 ...An之间仅存在N对认识关系:(A1A2)(A2A3)...(AnA1),而没有其它认识关系.比如四边关系指ABCD四个人 AB,BC,C D,DA相互认识,而AC,BD不认识.

全民比赛时,为了防止做弊,规定任意一对相互认识的人不得在一队,国王相知道, 最少可以分多少支队。

用最少的颜色给每个点染色使得相邻点颜色不同

诱导子图:某些点和始图中连接这些点的边

 团:

 完全图:每两个点都有一条边相连

单纯点:设N(v)表示与v相连的点集,一个点称为单纯点当{v}+N(v)的诱导子图是一个团

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

一个无向图是弦图当且仅当它有一个完美消除序列

最大势算法:从n到1依次给点标号(标号为i代表出现在完美消除序列的第i个)

用label[i]代表第i个点与多少已标号的点相连,每次找label[i]最大的没标号的点标号

 

 

 ......

 本题生成一个完美消除序列,按照完美消除序列倒序遍历点,染上当前能染的最小颜色

 

#include<bits/stdc++.h>
#define REP(i,st,en) for(int i=st;i>=en;i--)
#define rep(i,st,en) for(int i=st;i<=en;i++)
using namespace std;
typedef long long ll;
vector<int>v;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct node
{
	int to,next;
}e[2000100];
int n,m,x,op,a,b,cnt,head[2000100],vis[2000100],d[2000100],que[2000100],has[2000100],col[2000100],ans;
void add(int u,int v)
{e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;}
int main()
{
	scanf("%d%d",&n,&m);
	while(m--)
	{
		a=read(),b=read();
		add(a,b),add(b,a);
	}
	REP(i,n,1)//生成完美消除序列 
	{
		int t=0;
		for(int j=1;j<=n;j++)
			if(!vis[j]&&d[j]>=d[t])
				t=j;//找到没标号的最大值 
		vis[t]=1;que[i]=t;//加入完美消除序列 
		for(int j=head[t];j;j=e[j].next)
			d[e[j].to]++;//连接的每个点degree++
	}
	REP(i,n,1)
	{
		int t=que[i];//在完美消除序列中从后往前遍历 
		for(int j=head[t];j;j=e[j].next)
			has[col[e[j].to]]=i;//标记相邻点的color在第i个点不能染 
		int j;
		for(j=1;;j++)
			if(has[j]!=i)
				break;
		col[t]=j;//找到最小能染的color 
		if(j>ans)
			ans=j;//记录最大的color编号,也就是数量 
	}
	printf("%d",ans);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值