#1996 [HNOI2008]神奇的国度 【最大势算法】

版权声明:----------------------------------------转载是ok的,但要附上出处哟 https://blog.csdn.net/qq_43040655/article/details/87115327

大意:
给一个无向图,用最少种颜色染色,使得相邻点颜色不同。

是一个mcs问题,具体算法及详细背景参见:
https://wenku.baidu.com/view/07f4be196c175f0e7cd13784.html

几点注意:

结论很微妙,要加深理解,就是求一个“完美序列”

优化方法要注意,因为数值规模不大,用链表来实现最大值查询,少一个log(否则过不了)

这种染色就是打标记嘛,一个点肯定不能和相邻的方成一组,所以相邻的标记++

注:最初所有点都是0,因为相邻才会++

每次选 标记数 最大 的入队 ,每一次删除相当于增加了 标记为 i 号的集合,肯定要选最“冲突”的 删除

#include<queue>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<string>
#include<algorithm>
#define pf printf
#define sf scanf


using namespace std;
const int maxm=1e6+10,maxn=1e4+10;
int head[maxn<<1],cnt=1,s[maxn],ans=0,n,m;
struct edge{
	int nxt,v;
}e[maxm<<2];
inline void _add(int u,int v){
	e[++cnt]=(edge){head[u],v};
	head[u]=cnt;
}
int hash[maxn];
bool vis[maxn<<1];
signed main (){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)hash[i]=n+i+1;
	for(int i=1;i<=m;++i){
		int a,b;sf("%d%d",&a,&b);
		_add(a,b),_add(b,a);
	}
	for(int i=1;i<=n;++i)_add(hash[0],i);
	int loc=0;
	for(int i=1;i<=n;++i){
		bool flag=0;
		for(int &j=head[hash[loc]];j;j=e[j].nxt){
			int v=e[j].v;
			if(vis[v])continue;
			flag=1;vis[v]=1;
			for(int k=head[v];k;k=e[k].nxt){
				int vv=e[k].v;if(vis[vv])continue;
				++s[vv];
				_add(hash[s[vv]],vv);
				loc=max(loc,s[vv]);
			}
			break;
		}
		ans=max(ans,loc);
		if(!flag)--loc,--i;
	}
	printf("%d",ans+1);

	   return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43040655/article/details/87115327