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


    弦图最小染色/MCS算法


      Orz PoPoQQQ  (UPD:ydc的写法好像更熟悉一些……(类似堆优化的Dij啊~

      先留个坑……明天再看一看……感觉好神奇>_<(完美消除序列之于弦图 就好似 拓扑序列之于DAG,所以弦图的问题许多都要靠这个完美消除序列来做)

     1 /**************************************************************
     2     Problem: 1006
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:536 ms
     7     Memory:34996 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 1006
    11 #include<vector>
    12 #include<cstdio>
    13 #include<cstdlib>
    14 #include<cstring>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 using namespace std;
    21  
    22 int getint(){
    23     int v=0,sign=1; char ch=getchar();
    24     while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
    25     while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();}
    26     return v*sign;
    27 }
    28 typedef long long LL;
    29 const int N=100010,INF=~0u>>2;
    30 /*******************tamplate********************/
    31 struct List{
    32     int to,next;
    33 }table[4004004];
    34 int head[N],tot; 
    35 int n,m,ans,best,f[N],list[N],seq[N],color[N],mark[N];
    36 bool v[N];
    37 void add(int *h,int x,int y){
    38     table[++tot].to=y;
    39     table[tot].next=h[x];
    40     h[x]=tot;
    41 }
    42 void MCS(){
    43     int i,j;
    44     F(i,1,n) add(list,0,i);
    45     D(j,n,1){
    46         while(1){
    47             for(i=list[best];i;i=table[i].next){
    48                 if (!v[table[i].to]) break;
    49                 else list[best]=table[i].next;
    50             }
    51             if (i){
    52                 int x=table[i].to;
    53                 v[x]=1; seq[j]=x;
    54                 for(i=head[x];i;i=table[i].next)
    55                     if(!v[table[i].to]){
    56                         f[table[i].to]++;
    57                         add(list,f[table[i].to],table[i].to);
    58                         best=max(best,f[table[i].to]);
    59                     }
    60                 break;
    61             }else best--;
    62         }
    63     }
    64 }
    65 int main(){
    66 #ifndef ONLINE_JUDGE
    67     freopen("input.txt","r",stdin);
    68 //  freopen("output.txt","w",stdout);
    69 #endif
    70     n=getint(); m=getint();
    71     int x,y;
    72     F(i,1,m){
    73         x=getint(); y=getint();
    74         add(head,x,y);
    75         add(head,y,x);
    76     }
    77     MCS();
    78     D(j,n,1){
    79         int x=seq[j],i;
    80         for(int i=head[x];i;i=table[i].next)
    81             mark[ color[table[i].to] ]=j;
    82         for(i=1;i<=n && mark[i]==j;i++);
    83         color[x]=i;
    84         ans=max(ans,i);
    85     }
    86     printf("%d
    ",ans);
    87     return 0;
    88 }
    View Code

    UPD:重新看了下论文理解了一下>_< (2015-04-09 08:41:04)

     1 /**************************************************************
     2     Problem: 1006
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:536 ms
     7     Memory:34996 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 1006
    11 #include<vector>
    12 #include<cstdio>
    13 #include<cstdlib>
    14 #include<cstring>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 using namespace std;
    21  
    22 int getint(){
    23     int v=0,sign=1; char ch=getchar();
    24     while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
    25     while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();}
    26     return v*sign;
    27 }
    28 typedef long long LL;
    29 const int N=100010,INF=~0u>>2;
    30 /*******************tamplate********************/
    31 struct List{
    32     int to,next;
    33 }table[4004004];
    34 int head[N],tot; 
    35 int n,m,ans,best,f[N],list[N],seq[N],color[N],mark[N];
    36 bool v[N];
    37 void add(int *h,int x,int y){
    38     table[++tot].to=y;
    39     table[tot].next=h[x];
    40     h[x]=tot;
    41 }
    42 void MCS(){
    43     int i,j;
    44     F(i,1,n) add(list,0,i);//一开始全部加入标号为0的桶 
    45     D(j,n,1){//倒着生成完美消除序列 
    46         while(1){
    47             for(i=list[best];i;i=table[i].next){
    48                 if (!v[table[i].to]) break;
    49                 //找一个标号最大的未访问节点
    50                 else list[best]=table[i].next;
    51                 //在链表中删除头结点(因为已访问过) 
    52             }
    53             if (i){//如果当前最大的标号里有一个未访问过的节点(找到了!) 
    54                 int x=table[i].to;
    55                 v[x]=1; seq[j]=x;
    56                 //标记当前节点已访问过,将x放进完美消除序列
    57                 for(i=head[x];i;i=table[i].next)
    58                     if(!v[table[i].to]){
    59                         f[table[i].to]++;//如果相连的这个节点是未访问过的那么它的“势”+1 
    60                         add(list,f[table[i].to],table[i].to);
    61                         //将这个节点插入到更高标号的桶里面去 
    62                         best=max(best,f[table[i].to]);
    63                         //更新最大标号看是否增加了 
    64                     }
    65                 break;
    66             }else best--;//如果当前最大的标号里没有未访问过的节点
    67                          //那么最大标号-1,循环回去重新找best-1里有没有 
    68         }//无限循环直到找到一个可以更新的节点(外层循环固定了找n次) 
    69     }
    70 }
    71 int main(){
    72 #ifndef ONLINE_JUDGE
    73     freopen("input.txt","r",stdin);
    74 //  freopen("output.txt","w",stdout);
    75 #endif
    76     n=getint(); m=getint();
    77     int x,y;
    78     F(i,1,m){
    79         x=getint(); y=getint();
    80         add(head,x,y);
    81         add(head,y,x);
    82     }
    83     MCS();
    84     D(j,n,1){
    85         int x=seq[j],i;
    86         for(int i=head[x];i;i=table[i].next)
    87             mark[ color[table[i].to] ]=j;
    88         for(i=1;i<=n && mark[i]==j;i++);
    89         color[x]=i;
    90         ans=max(ans,i);
    91     }
    92     printf("%d
    ",ans);
    93     return 0;
    94 }
    View Code(加注释)

    1006: [HNOI2008]神奇的国度

    Time Limit: 20 Sec  Memory Limit: 162 MB
    Submit: 2208  Solved: 989
    [Submit][Status][Discuss]

    Description

    K 国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关 系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2...An之间仅存在N对认识关系:(A1A2)(A2A3)...(AnA1),而没有其它认识关系.比如四边关系指ABCD四个人 AB,BC,CD,DA相互认识,而AC,BD不认识.全民比赛时,为了防止做弊,规定任意一对相互认识的人不得在一队,国王相知道,最少可以分多少支 队。

    Input

    第一行两个整数N,M。1<=N<=10000,1<=M<=1000000.表示有N个人,M对认识关系. 接下来M行每行输入一对朋友

    Output

    输出一个整数,最少可以分多少队

    Sample Input

    4 5
    1 2
    1 4
    2 4
    2 3
    3 4

    Sample Output

    3

    HINT

    一种方案(1,3)(2)(4)

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    Longest Common Substring
    未完成 Anagrams
    strStr
    vim的学习笔记
    Compare Strings
    Two Strings Are Anagrams
    KMP算法
    [ 力扣活动0314 ] 300. 最长上升子序列
    [ 力扣活动0317 ] 1160. 拼写单词
    [ 力扣活动0313 ] 169. 多数元素
  • 原文地址:https://www.cnblogs.com/Tunix/p/4405186.html
Copyright © 2020-2023  润新知