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


    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维护了一下最大= =因为链表的话感觉很麻烦写= =

  • 相关阅读:
    第十九天:类和对象
    第十五天:模块
    十四天:匿名函数
    十四天作业
    第十三天:迭代器、递归
    十二天:闭包和装饰器
    一个炒鸡简单的购物车
    十一天
    第十天
    第十天作业
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4293953.html
Copyright © 2020-2023  润新知