• 弦图问题初步


    弦图是什么:一个无向图称为弦图当图中任意长度大于3的环都至少有一个弦(不存在中间无边的长度大于三的环)

    弦图的每一个诱导子图一定是弦图。
    弦图的判定:用MCS求完美消除子序列,再判断求出来的是否是完美消除序列。
    ž定理:一个无向图是弦图当且仅当它有一个完美消除序列。
     
    单纯点(simplicial vertex):设N(v)表示与点v相邻的点集。一个点称为单纯点当{v} + N(v)的诱导子图为一个团。
    ž完美消除序列(perfect elimination ordering)
    ž定义:一个点的序列(每个点出现且恰好出现一次)v1, v2, …, vn满足vi在{vi, vi+1,…,vn}的诱导子图中为一个单纯点。
     
    MCS:从1--n给点标号。先任意选一个点作为完美消除序列的末尾,在将它相邻的点势能+1;在选取势能最大的点,并重复+1的步骤,直至标号到1。用链表实现这个过程
    完美消除序列判定:从后往前扫,利用已经判断过的点是单纯点(即可以构成团)设{vi+1,…,vn}中所有与vi相邻的点依次为vj1, …, vjk。只需判断vj1是否与vj2, …, vjk相邻即可(注意:vj1是已经判定过的点中标号最小的点)。
     
    弦图染色:用最少的颜色给每个点染色使得相邻的点染的颜色不同。
    完美消除序列从后往前依次给每个点染色,给每个点染上可以染的最小的颜色。
     
    弦图最大独立集:ž选择最多的点使得任意两个点不相邻。
    完美消除序列从前往后能选就选。
     
    弦图最小团覆盖:用最少个数的团覆盖所有的点。
    最大独立集数 = 最小团覆盖数
     
    弦图应用
     
    ž区间图(Interval Graph)
    定义: 给定一些区间,定义一个相交图为每个顶点表示一个区间,两个点有边当且仅当两个区间的交集非空。
    一个图为区间图当它是若干个区间的相交图。
    ž区间图一定是弦图。
     
    经典问题:
    1. 给定n个区间,要求选择最多的区间使得区间不互相重叠: 建区间图,相当于求最大独立集
    2. ž有n个积木,高度均为1,第i个积木的宽度范围为[Li,  Ri],选择一个积木的下落顺序使得最后积木总高度尽可能小: 弦图最小染色、同一种颜色表示可以出现在同一层
     
    例题1:
    bzoj 1006 神奇的国度
     
    弦图染色裸题
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 #define maxn 1002000
     7 #define maxm 10020
     8 
     9 struct node{
    10     int next,to;
    11 }e[maxn * 2];
    12 struct node2{
    13     int id,next;
    14 }link_[maxn * 2];
    15 int hd[maxn];
    16 int head[maxn],cnt;
    17 int n,m;
    18 int col[maxn],tot,vis[maxn],lb[maxn];
    19 int a[maxn];
    20 
    21 inline void adde(int x,int y){
    22     e[++cnt].to = y;
    23     e[cnt].next = head[x];
    24     head[x] = cnt;
    25 }
    26 inline void insert(int x,int y){
    27     int a = hd[x];
    28     hd[x] = ++tot;
    29     link_[tot].id = y , link_[tot].next = a;    
    30 }
    31 inline void del(int x){
    32     hd[x] = link_[hd[x]].next;
    33 }
    34 inline int find(int x){
    35     while ( hd[x] ){
    36         if ( !vis[link_[hd[x]].id] ) return link_[hd[x]].id;
    37         hd[x] = link_[hd[x]].next;
    38     }
    39     return 0;
    40 }
    41 void MCS(){
    42     for (int i = 1 ; i <= n ; i++){
    43         insert(0,i);
    44     }
    45     a[n] = 1 , vis[1] = 1;
    46     for (int i = head[1] ; i ; i = e[i].next){
    47         insert(++lb[e[i].to],e[i].to);
    48     }
    49     int p = 1;
    50     for (int i = n - 1 ; i >= 1 ; i--){
    51         int cur = 0;
    52         while ( !cur && p >= 0 ) cur = find(p) , p--;
    53         p++;
    54         vis[cur] = 1 , a[i] = cur;
    55         for (int i = head[cur] ; i ; i = e[i].next){
    56             insert(++lb[e[i].to],e[i].to);
    57             p = max(p,lb[e[i].to]);
    58         }
    59     }
    60 }
    61 void solve(){
    62     for (int i = 1 ; i <= n ; i++) vis[i] = 0;
    63     tot = 0;
    64     for (int i = n ; i >= 1 ; i--){
    65         int j = 0;
    66         for (j = head[a[i]] ; j ; j = e[j].next){
    67             vis[col[e[j].to]] = 1;
    68         }
    69         j = 1;
    70         while ( vis[j] ) j++;
    71         col[a[i]] = j;
    72         for (j = head[a[i]] ; j ; j = e[j].next){
    73             vis[col[e[j].to]] = 0;
    74         }    
    75     }
    76     for (int i = 1 ; i <= n ; i++) tot = max(tot,col[i]);
    77     printf("%d
    ",tot);
    78 }
    79 int main(){
    80     //freopen("input.txt","r",stdin);
    81     scanf("%d %d",&n,&m);
    82     for (int i = 1 ; i <= m ; i++){
    83         int x,y;
    84         scanf("%d %d",&x,&y);
    85         adde(x,y);
    86         adde(y,x);
    87     }
    88     MCS();
    89     solve();
    90     return 0;
    91 }
     
    例题2:
    bzoj 124 Zju1015 Fishing Net弦图判定
     
    弦图判定裸题
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 #define maxn 1002000
     7 #define maxm 10020
     8 
     9 struct node{
    10     int next,to;
    11 }e[maxn * 2];
    12 struct node2{
    13     int id,next;
    14 }link_[maxn * 2];
    15 int hd[maxn];
    16 int head[maxn],cnt;
    17 int n,m;
    18 int c[maxn],tot,vis[maxn],lb[maxn],use[maxn];
    19 int a[maxn],dfstime;
    20 
    21 inline void adde(int x,int y){
    22     e[++cnt].to = y;
    23     e[cnt].next = head[x];
    24     head[x] = cnt;
    25 }
    26 inline void insert(int x,int y){
    27     int a = hd[x];
    28     hd[x] = ++tot;
    29     link_[tot].id = y , link_[tot].next = a;    
    30 }
    31 inline void del(int x){
    32     hd[x] = link_[hd[x]].next;
    33 }
    34 inline int find(int x){
    35     while ( hd[x] ){
    36         if ( !vis[link_[hd[x]].id] ) return link_[hd[x]].id;
    37         hd[x] = link_[hd[x]].next;
    38     }
    39     return 0;
    40 }
    41 void MCS(){
    42     for (int i = 1 ; i <= n ; i++){
    43         insert(0,i);
    44     }
    45     a[n] = 1 , vis[1] = 1;
    46     for (int i = head[1] ; i ; i = e[i].next){
    47         insert(++lb[e[i].to],e[i].to);
    48     }
    49     int p = 1;
    50     for (int i = n - 1 ; i >= 1 ; i--){
    51         int cur = 0;
    52         while ( !cur && p >= 0 ) cur = find(p) , p--;
    53         p++;
    54         vis[cur] = 1 , a[i] = cur;
    55         for (int i = head[cur] ; i ; i = e[i].next){
    56             insert(++lb[e[i].to],e[i].to);
    57             p = max(p,lb[e[i].to]);
    58         }
    59     }
    60 }
    61 bool check(){
    62     for (int i = 1 ; i <= n ; i++) vis[i] = 0;
    63     use[a[n]] = 1;
    64     for (int i = n - 1 ; i >= 1 ; i--){
    65         dfstime++, cnt = 0;
    66         for (int j = head[a[i]] ; j ; j = e[j].next){
    67             if ( use[e[j].to] ) c[++cnt] = e[j].to;
    68         }
    69         for (int j = head[c[1]] ; j ; j = e[j].next){
    70             vis[e[j].to] = dfstime;
    71         }
    72         for (int j = 2 ; j <= cnt ; j++) if ( vis[c[j]] != dfstime ) return 0;
    73         use[a[i]] = 1;
    74     }
    75     return 1;
    76 }
    77 int main(){
    78     //freopen("input.txt","r",stdin);
    79     scanf("%d %d",&n,&m);
    80     for (int i = 1 ; i <= m ; i++){
    81         int x,y;
    82         scanf("%d %d",&x,&y);
    83         adde(x,y);
    84         adde(y,x);
    85     }
    86     MCS();
    87     if ( check() ) printf("Perfect
    ");
    88     else printf("Imperfect
    ");
    89     return 0;
    90 }

    就先写这么多吧,以后遇到好题再加(现在只有裸题,好惨)

     
  • 相关阅读:
    iOS CoreData使用笔记
    iOS UIWebView中添加手势
    Swift sha1 md5加密
    Swift用block响应UIAlertView和UIActionSheet的按钮点击事件
    iOS判断iPhone型号
    iOS Document Interaction 编程指南
    Swift项目开发中缓存计算以及清除
    SVN 一次性提交多个目录中文件
    svn 相关
    sublime text 2相关
  • 原文地址:https://www.cnblogs.com/zqq123/p/5466478.html
Copyright © 2020-2023  润新知