题目
分析
弦图,想到完美消除序列,首先用MCS算法求出来。
MCS算法:
http://wenku.baidu.com/view/6f9f2223dd36a32d73758126.html?re=view
http://tieba.baidu.com/p/2891159900
MCS写
O(nlogn)
的算法就算了,
O(n+m)
的肯定会老是忘掉……
本图一定满足: 染色用的颜色数
≤
最大团的大小。
现在只用证明出这个极限即可,证明出这个极限的方法也可用于求染色用的最少颜色数。
我们从最后一个结点开始,每次找完美消除序列之后的所有不同颜色,将时间戳存到一个桶中。再遍历一遍桶,找出最小的没出现过的。
这样的算法就可以构造出答案。
代码
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
using namespace std;
const int N=10001;
const int M=1000001;
struct G
{
int v,nxt;
}map[M+M];
int tt,hd[N]; //Graph
int lab[N],tid[N],seq[N];
int color[N],r[N],colornum;
int n,m;
struct node
{
int w,id;
friend bool operator<(node a,node b)
{
return a.w<b.w;
}
};
priority_queue<node> q;
inline int read(void)
{
int s=0,f=1; char c=getchar();
for (;c<'0'||c>'9';c=getchar());
for (;'0'<=c&&c<='9';c=getchar()) s=s*10+c-48;
return s*f;
}
inline void ins(int u,int v)
{
map[++tt].v=v;
map[tt].nxt=hd[u];
hd[u]=tt;
}
void init_graph(void)
{
int x,y;
n=read(),m=read();
for (int i=1;i<=m;i++)
{
x=read(),y=read();
ins(x,y),ins(y,x);
}
}
void get_queue(void)
{
node t;
for (int i=1;i<=n;i++)
{
t.id=i,t.w=lab[i];
q.push(t);
}
for (int num=n;num>0;num--)
{
for (;!q.empty();)
{
t=q.top(),q.pop();
if (!tid[t.id]) break;
}
seq[num]=t.id,tid[t.id]=num;
for (int k=hd[t.id];k;k=map[k].nxt)
if (!tid[map[k].v])
{
lab[map[k].v]++;
t.id=map[k].v;
t.w=lab[map[k].v];
q.push(t);
}
}
}
void color_graph(void)
{
int now;
for (int num=n;num>0;num--)
{
now=seq[num];
for (int k=hd[now];k;k=map[k].nxt)
if (tid[map[k].v]>num) r[color[map[k].v]]=now;
int d=0;
for (int k=1;k<=colornum;k++)
if (r[k]^now)
{
color[now]=k;
d=1; break;
}
if (!d) color[now]=++colornum;
}
printf("%d\n",colornum);
}
int main(void)
{
init_graph();
get_queue();
color_graph();
return 0;
}