http://www.lydsy.com/JudgeOnline/problem.php?id=1006
题意:在一个弦图中找最少染色数。(n<=10000, m<=1000000)
#include <bits/stdc++.h> using namespace std; const int N=10005, M=1000005; int n, m, ihead[N], tag[N], cnt, pos[N]; bool vis[N]; struct E { int next, to; }e[M<<1]; void add(int u, int v) { e[++cnt]={ihead[u], v}; ihead[u]=cnt; e[++cnt]={ihead[v], u}; ihead[v]=cnt; } #define pii pair<int, int> #define mkpii make_pair<int, int> set<pii> s; inline int getmx() { set<pii>::iterator it=s.end(); --it; int ret=(*it).second; s.erase(s.find(mkpii((*it).first, ret))); return ret; } inline void fix(int x) { s.erase(s.find(mkpii(tag[x], x))); ++tag[x]; s.insert(mkpii(tag[x], x)); } int getans() { int ret=0; for(int i=1; i<=n; ++i) s.insert(mkpii(0, i)); for(int now=n; now; --now) { int x=getmx(), ans=1; pos[x]=now; for(int i=ihead[x]; i; i=e[i].next) if(!pos[e[i].to]) fix(e[i].to); for(int i=ihead[x]; i; i=e[i].next) if(pos[e[i].to]>pos[x] && !vis[e[i].to]) ++ans, vis[e[i].to]=1; for(int i=ihead[x]; i; i=e[i].next) if(pos[e[i].to]>pos[x]) vis[e[i].to]=0; ret=max(ret, ans); } return ret; } int main() { scanf("%d%d", &n, &m); for(int i=0; i<m; ++i) { int x, y; scanf("%d%d", &x, &y); add(x, y); } printf("%d ", getans()); return 0; }
题解:
定理1:色数>=团数
定理2:最小色数=极大团数
定理1不会证QAQ(如此显然的东西竟然没看出来?
定理2挺简单的,看cdq论文= =
所以我们找最大的团就行了= =
于是就完了= =
用set维护了一下最大= =因为链表的话感觉很麻烦写= =