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

【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1006

【题意】

【题解】

好难.
先去看《弦图与区间图》那篇论文吧;
链接:http://wenku.baidu.com/link?url=xPkoWrdBJLV-F4QK7UfQ-HUo1QMW9epLvlfWonqS4Lj_pLnPomIL0MGUHTZJVrL3NlKfvYLs96WVf6omArLEX2AmElV0Z80yANnVzidmeGW
所给的要求就是把这张图约束成弦图吧。
这里说一下那个MCS(最大势)算法求完美消除序列的原理;
【单纯点】的定义是说,与这个点相连的点,和这个点本身,构成的诱导子图是一个完全图(团);
然后又说每个弦图都有【单纯点】,且把这个单存点和与之相连的边去掉之后,剩下的图也是一个弦图,
这样就存在一个递归的关系吧;
所以就从图最小的情况开始考虑;
即只有一个点然后慢慢地扩展到整张图;
又说弦图必然有完美消除序列;
所以这样的扩展最后一定能够得到整张图;
【但是我还是没办法理解为什么要选度数最多的吧】。
总之
做法就是
每次选度数最多的,且还没有被标号的点;
逆序处理出完美消除序列的各个元素;
然后同样的逆序运用这个消除序列;
(正序可以吗?应该不行吧..)
先逆序找到消除序列的第i个点;
对于第i个点,看看与之直接相连的点里面有哪些颜色;
你每次选择不在这些相邻的节点的颜色集中颜色编号最小的那个颜色,然后涂在这个i号点上就可以了;
最后不同颜色的数目就是所需要的最小组队个数了;
(组队的个数就相当于是不同颜色的个数,相同颜色的人就分在一组,也即相邻的点不能染成相同的颜色->对应有直接关系的人不能分在一个组里面)
这里我还是不能理解为什么这样做就可以了;
那个ppt里面的
T=团数那个地方我不懂;
我不知道那个团数指的是什么;
如果我知道T=团数是什么意思了;
那么根据前面的定理
团数<=色数;
再根据T>=色数;
就能得出团数>=色数;
则T=团数=色数了;
(这里的色数指的就是最小的染色数目);
T则是我们这样做最后染的不同颜色的颜色数目;
当然我不知道为什么T=团数,以及团数是什么。。
在欺骗自己懂这些东西之后.就能写出程序来了;
程序不难懂;

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 1e4+100,M = 1e6+100;

struct abc
{
    int en,nex;
};

abc bian[M*2];
int n,m,fir[N],q[N],cor[N];
int du[N],bo[N],tot;
bool vis[N];

void add(int x,int y)
{
    bian[++tot].nex = fir[x];
    fir[x] = tot;
    bian[tot].en = y;
}

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    rei(n),rei(m);
    rep1(i,1,m)
    {
        int x,y;
        rei(x),rei(y);
        add(x,y),add(y,x);
    }
    rep2(i,n,1)
    {
        int k = 0;
        rep1(j,1,n)
            if (!vis[j] && du[j]>=du[k])
                k = j;
        vis[k] = true,q[i] = k;
        for (int j = fir[k];j;j = bian[j].nex)
            du[bian[j].en]++;
    }
    int ans = 0;
    rep2(i,n,1)
    {
        int t = q[i];
        for (int j = fir[t];j;j = bian[j].nex)
        {
            int y = bian[j].en;
            bo[cor[y]] = t;
        }
        int k = -1;
        for (int j = 1;;j++)
            if (bo[j]!=t)
            {k = j;break;}
        cor[t] = k;
        if (k > ans)
            ans = k;
    }
    printf("%d\n",ans);
    return 0;
}
posted @ 2017-10-04 18:45  AWCXV  阅读(102)  评论(0编辑  收藏  举报