BZOJ1006 HNOI2008 神奇的国度
这个题目是一个弦图的经典题、
先用MCS求完美消除序列然后逆序贪心染色,求一个最小染色数就可以了~
Code:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <set> using namespace std; multiset <int> list[10001]; set <int> ban[10001]; int t[2000001],next[2000001]; int cnt[10001],g[10001],e[10001],p[10001],v[10001]; int n,m,aa,bb,r=0,maxn,maxnow,totc,curc; int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=m;i++){ scanf("%d%d",&aa,&bb); t[++r]=bb;if (!g[aa]) g[aa]=e[aa]=r;else {next[e[aa]]=r;e[aa]=r;} t[++r]=aa;if (!g[bb]) g[bb]=e[bb]=r;else {next[e[bb]]=r;e[bb]=r;} } memset(p,0,sizeof p); for (int i=1;i<=n;i++) list[i].clear(); for (int i=n;i;i--){ maxnow=-1; for (int j=1;j<=n;j++) if (!p[j] && list[j].size()>maxnow){ maxnow=list[j].size(); maxn=j; } p[maxn]++;v[i]=maxn; for (int u=g[maxn];u;u=next[u]) list[t[u]].insert(maxn); } totc=0; for (int i=n;i;i--){ curc=1; while (ban[v[i]].count(curc)) curc++; if (curc>totc) totc++; for (int u=g[v[i]];u;u=next[u]) if (!ban[t[u]].count(curc)) ban[t[u]].insert(curc); } printf("%d\n",totc); return 0; }