【BZOJ】1006 神奇的国度

【解析】完美消除序列+染色

[Analysis]

由题知他们的关系构成一个弦图,所以求出完美消除序列一定是成立的。

先求出,然后根据序列来染色,尽可能染小的。

其实时间戳那里用个线段树+二分好像也不错,甚至树状数组都可以,因为元素的变化是单调的...

在此给出证明:

首先进行以下的定义:

团数:最大团的大小。

色数:染色最少用的颜色。

∵团中颜色要两两不同

∴团数<=色数

∵我们对序列的染色共染了t种颜色且这样的染色是合法的,但是暂时不能保证最少。

∴t>=色数。

又∵我们的染色方法是贪心的,遇到团的最后一个元素染色最大

∴t=团数。

∴团数>=色数,团数<=色数

∴团数=色数。

∴t=团数=色数,证毕。

ppt中O(n+m)的实现很多都没讲清楚,戳这里可以看MCS的实现:http://tieba.baidu.com/p/2891159900。

[Sum]

①弦图的团数=色数。

②完美消除序列的三种求法:暴力,优先队列,线性。

③如果要更改队列里的元素,等价于重新在插入元素,这样原来队列里的元素不会产生影响。

在优先队列、链表等多种数据结构中用到。

④记录时间戳染色的方法。

[Code]优先队列

**************************************************************
    Problem: 1006
    User: y20070316
    Language: C++
    Result: Accepted
    Time:848 ms
    Memory:28960 kb
****************************************************************/

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
using namespace std;

const int N=10001;
const int M=1000001;

struct G
{
    int v,nxt;
}map[M+M];
int tt,hd[N];   //Graph
int lab[N],tid[N],seq[N];
int color[N],r[N],colornum;
int n,m;
struct node
{
    int w,id;
    friend bool operator<(node a,node b)
    {
        return a.w<b.w;
    }
};
priority_queue<node> q;

inline int read(void)
{
    int s=0,f=1; char c=getchar();
    for (;c<'0'||c>'9';c=getchar());
    for (;'0'<=c&&c<='9';c=getchar()) s=s*10+c-48;
    return s*f;
}

inline void ins(int u,int v)
{
    map[++tt].v=v;
    map[tt].nxt=hd[u];
    hd[u]=tt;
}

void init_graph(void)
{
    int x,y;
    n=read(),m=read();
    for (int i=1;i<=m;i++)
    {
        x=read(),y=read();
        ins(x,y),ins(y,x);
    }
}

void get_queue(void)
{
    node t;
    for (int i=1;i<=n;i++)
    {
        t.id=i,t.w=lab[i];
        q.push(t);
    }
    for (int num=n;num>0;num--)
    {
        for (;!q.empty();)
        {
            t=q.top(),q.pop();
            if (!tid[t.id]) break;
        }
        seq[num]=t.id,tid[t.id]=num;
        for (int k=hd[t.id];k;k=map[k].nxt)
            if (!tid[map[k].v])
            {
                lab[map[k].v]++;
                t.id=map[k].v;
                t.w=lab[map[k].v];
                q.push(t);
            }
    }
}

void color_graph(void)
{
    int now;
    for (int num=n;num>0;num--)
    {
        now=seq[num];
        for (int k=hd[now];k;k=map[k].nxt)
            if (tid[map[k].v]>num) r[color[map[k].v]]=now;
        int d=0;
        for (int k=1;k<=colornum;k++)
            if (r[k]^now)
            {
                color[now]=k;
                d=1; break;
            }
        if (!d) color[now]=++colornum;
    }
    printf("%d\n",colornum);
}

int main(void)
{
    init_graph();
    get_queue();
    color_graph();

    return 0;
}</span>

[Code]链表

<span style="font-size:18px;">/**************************************************************
    Problem: 1006
    User: y20070316
    Language: C++
    Result: Accepted
    Time:484 ms
    Memory:24596 kb
****************************************************************/

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
using namespace std;

const int N=10001;
const int M=1000001;

struct G
{
    int v,nxt;
}map[M+M];
int tt,hd[N];   //Graph
int lab[N],tid[N],seq[N];
int color[N],r[N],colornum;
int n,m;
G list[N+M]; int mxf,lhd[N],tl; //List for MCS

inline int read(void)
{
    int s=0,f=1; char c=getchar();
    for (;c<'0'||c>'9';c=getchar());
    for (;'0'<=c&&c<='9';c=getchar()) s=s*10+c-48;
    return s*f;
}

inline void insg(int u,int v)
{
    map[++tt].v=v;
    map[tt].nxt=hd[u];
    hd[u]=tt;
}

void init_graph(void)
{
    int x,y;
    n=read(),m=read();
    for (int i=1;i<=m;i++)
    {
        x=read(),y=read();
        insg(x,y),insg(y,x);
    }
}

inline void inslist(int floor,int id)
{
    list[++tl].v=id;
    list[tl].nxt=lhd[floor];
    lhd[floor]=tl;
}

void get_queue(void)
{
    int now;
    for (int i=1;i<=n;i++) inslist(lab[i],i);
    for (int num=n;num>0;num--)
    {
        for (;tid[list[lhd[mxf]].v];)
        {
            lhd[mxf]=list[lhd[mxf]].nxt;
            if (!lhd[mxf]) mxf--;
        }
        now=list[lhd[mxf]].v; lhd[mxf]=list[lhd[mxf]].nxt;
        for (;!lhd[mxf];) mxf--;
        tid[now]=num,seq[num]=now;
        for (int k=hd[now];k;k=map[k].nxt)
            if (!tid[map[k].v])
            {
                lab[map[k].v]++;
                if (lab[map[k].v]>mxf) mxf=lab[map[k].v];
                inslist(lab[map[k].v],map[k].v);
            }
    }
}

void color_graph(void)
{
    int now;
    for (int num=n;num>0;num--)
    {
        now=seq[num];
        for (int k=hd[now];k;k=map[k].nxt)
            if (tid[map[k].v]>num) r[color[map[k].v]]=now;
        int d=0;
        for (int k=1;k<=colornum;k++)
            if (r[k]^now)
            {
                color[now]=k;
                d=1; break;
            }
        if (!d) color[now]=++colornum;
    }
    printf("%d\n",colornum);
}

int main(void)
{
    init_graph();
    get_queue();
    color_graph();

    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-05 04:03:50

【BZOJ】1006 神奇的国度的相关文章

BZOJ 1006 神奇的国度(弦图的染色数)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1006 题意:给定一个弦图,求最小染色数.就是用最小数目的颜色进行染色使得任意两个相邻的节点颜色不同. 思路:(1)求出弦图的完美消除序列. (2)贪心染色.从后向前用可以用的编号最小的颜色染色.在这里因为最小染色等于最大团,我直接求的最大团.为什么最小染色等于最大团呢?最大团w(G) 是包含点数最多的团,最小染色x(G)是相邻点不同色的最小颜色个数.那么w(G)<=x(G),因为最大团

bzoj 1006 神奇的国度

题目大意: 一个弦图,求最小点染色 思路: 使用最大势算法 完美消除序列从后往前依次给每个点,给每个点染上可以染的最小的颜色 --cdq 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<queue> 8 #inc

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

弦图最小染色/MCS算法 Orz PoPoQQQ  (UPD:ydc的写法好像更熟悉一些……(类似堆优化的Dij啊~ 先留个坑……明天再看一看……感觉好神奇>_<(完美消除序列之于弦图 就好似 拓扑序列之于DAG,所以弦图的问题许多都要靠这个完美消除序列来做) 1 /************************************************************** 2 Problem: 1006 3 User: Tunix 4 Language: C++ 5 Resu

bzoj 1006: [HNOI2008]神奇的国度 弦图的染色问题&amp;&amp;弦图的完美消除序列

1006: [HNOI2008]神奇的国度 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1788  Solved: 775[Submit][Status] Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2...An之间仅存在N对认识关系:(A1A2)

BZOJ 1006: [HNOI2008]神奇的国度( MCS )

弦图最小染色...先用MCS求出完美消除序列然后再暴力染色... ------------------------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; const int maxn = 10009; inline int read() { char c = getchar(); int ret = 0; for(; !i

bzoj 1006: [HNOI2008]神奇的国度 -- 弦图(最大势算法)

1006: [HNOI2008]神奇的国度 Time Limit: 20 Sec  Memory Limit: 162 MB Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2...An之间仅存在N对认识关系:(A1A2)(A2A3)...(AnA1),而没有其它认识关系.比如四边关系指ABCD四个人

【最小染色】【HNOI 2008】【bzoj 1006】神奇的国度

1006: [HNOI2008]神奇的国度 Time Limit: 20 Sec Memory Limit: 162 MB Submit: 2446 Solved: 1101 Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2-An之间仅存在N对认识关系:(A1A2)(A2A3)-(AnA1),而没有其

BZOJ 1006: [HNOI2008]神奇的国度 弦图的最小染色问题

弦图的最小染色问题: 先求出完美消除序列,然后从后往前贪心染色 1006: [HNOI2008]神奇的国度 Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 2245  Solved: 1006 [Submit][Status][Discuss] Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等

[BZOJ 1006] [HNOI2008] 神奇的国度 【弦图最小染色】

题目链接: BZOJ - 1006 题目分析 这道题是一个弦图最小染色数的裸的模型. 弦图的最小染色求法,先求出弦图的完美消除序列(MCS算法),再按照完美消除序列,从后向前倒着,给每个点染能染的最小颜色. 求出的颜色数就是最小染色,同时也是最大团. 代码 #include <iostream> #include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #in