大意:
给一个无向图,用最少种颜色染色,使得相邻点颜色不同。
是一个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;
}