码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ】1006: [HNOI2008]神奇的国度

时间:2015-02-16 13:02:02      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:

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\n", getans());
	return 0;
}

  

题解:

定理1:色数>=极大团数

定理2:最小色数=极大团数

定理3:极大团数=完美消除序列中$v_i$与$v_j, j>i$形成的诱导子图中$v_i$作为单纯点的团数。

定理1不会证QAQ

定理2挺简单的,看cdq论文= =

定理3也挺简单的= =看论文

于是就完了= =

用set维护了一下最大= =因为链表的话感觉很麻烦写= =

【BZOJ】1006: [HNOI2008]神奇的国度

标签:

原文地址:http://www.cnblogs.com/iwtwiioi/p/4293953.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!