zoukankan      html  css  js  c++  java
  • 最大团问题

    PS:看了百科你会晕,你会感觉这东西好难。  百科传送阵:http://baike.baidu.com/view/7343867.htm?fr=aladdin

    最大团:一幅无向图的顶点最多的(最大)完全子图。完全图就是每个点的度数都等于n-1的无向图。 百科传送阵: http://baike.baidu.com/view/2780567.htm?fr=aladdin

     

    有以下结论: 

    1、最大团点的数量=补图中最大独立集点的数量,二分图中,最大独立集点顶点个数= 顶点数 - 最大匹配数

    2、图的染色问题中,最少需要的颜色的数量=最大团点的数量

    可以看出来,我们可以通过最大匹配来解最大团问题。有一个问题需要解决,这种方式可不可以记录最大团中点的编号,因为有些题需要输出点。我们知道,在无向图中,最大匹配输等于求出的匹配数的二分之一。在记录与X集合匹配的点的时候,如果最大匹配的值是1,记录数组中就会有两个值不是-1(-1是初始化的)。那么到底哪一点是最大团里的呢?不能确定。所以通过最大匹配来求不适合。比较尴尬的是,我用Hopcroft-Karp算法来求补图中的最大匹配的方式来做的时候,hdu1530一直AC不了。所以这方法还是别用来,至少我不用了。

    网上流行的模版都是通过深搜来完成。传送门:http://www.cnblogs.com/zhj5chengfeng/archive/2013/07/29/3224092.html

    上面的博客讲的很好。就借用了。

    我的模版来自:http://blog.csdn.net/leolin_/article/details/7251962

    其实这模版上上面一个链接里的模版是一样。上面那个通过结构体封装了。下面的是C语言风格。

    模版:

    tuan[]记录最大团的顶点,ans就是所求的最大团的顶点数,num[i]表示由结点i到结点n构成的最大团的结点数,can[i]表示在已经确定了经选定的i个点必须在最大团内的前提下还有可能被加进最大团的结点集合,g[][]邻接矩阵(从1开始)。

     1 const int N=102;
     2 int ans;
     3 int x[N],tuan[N];
     4 int can[N][N];
     5 int num[N];
     6 bool g[N][N];
     7 int n,m;
     8 bool dfs(int tot,int cnt){
     9     int i,j,k;
    10     if(tot == 0){
    11         if(cnt > ans){
    12             ans = cnt;
    13             for(i=0;i<ans;i++){
    14                 tuan[i] = x[i];
    15             }
    16             return true;
    17         }
    18         return false;
    19     }
    20     for(i=0;i<tot;i++){
    21         if(cnt + (tot-i) <= ans)return false;
    22         if(cnt + num[can[cnt][i]] <= ans)return false;
    23         k = 0;
    24         x[cnt] = can[cnt][i];
    25         for(j=i+1;j<tot;j++){
    26             if(g[can[cnt][i]][can[cnt][j]]){
    27                 can[cnt+1][k++] = can[cnt][j];
    28             }
    29         }
    30         if(dfs(k,cnt+1))return false;
    31     }
    32     return false;
    33 }
    34 void mc(){
    35     int i,j,k;
    36     ans = 1;
    37     for(i=n;i>=1;i--){
    38         k = 0;
    39         x[0] = i;
    40         for(j=i+1;j<=n;j++){
    41             if(g[i][j]){
    42                 can[1][k++] = j;
    43             }
    44         }
    45         dfs(k,1);
    46         num[i] = ans;
    47     }
    48 }
    49 void init(){    memset(g,0,sizeof(g)); }
    View Code

    hdu 1530 Maximum Clique

    核对模版的题目

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=102;
     7 int ans;
     8 int x[N],tuan[N];
     9 int can[N][N];
    10 int num[N];
    11 bool g[N][N];
    12 int n,m;
    13 bool dfs(int tot,int cnt){
    14     int i,j,k;
    15     if(tot == 0){
    16         if(cnt > ans){
    17             ans = cnt;
    18             for(i=0;i<ans;i++){
    19                 tuan[i] = x[i];
    20             }
    21             return true;
    22         }
    23         return false;
    24     }
    25     for(i=0;i<tot;i++){
    26         if(cnt + (tot-i) <= ans)return false;
    27         if(cnt + num[can[cnt][i]] <= ans)return false;
    28         k = 0;
    29         x[cnt] = can[cnt][i];
    30         for(j=i+1;j<tot;j++){
    31             if(g[can[cnt][i]][can[cnt][j]]){
    32                 can[cnt+1][k++] = can[cnt][j];
    33             }
    34         }
    35         if(dfs(k,cnt+1))return false;
    36     }
    37     return false;
    38 }
    39 void mc(){
    40     int i,j,k;
    41     ans = 1;
    42     for(i=n;i>=1;i--){
    43         k = 0;
    44         x[0] = i;
    45         for(j=i+1;j<=n;j++){
    46             if(g[i][j]){
    47                 can[1][k++] = j;
    48             }
    49         }
    50         dfs(k,1);
    51         num[i] = ans;
    52     }
    53 }
    54 void init(){    memset(g,0,sizeof(g)); }
    55 
    56 int main()
    57 {
    58     //freopen("test.txt","r",stdin);
    59     int i,j;
    60     while(scanf("%d",&n)!=EOF&&n)
    61     {
    62         init();
    63         for(i=1;i<=n;i++)
    64             for(j=1;j<=n;j++)
    65                 scanf("%d",&g[i][j]);
    66         mc();
    67         printf("%d
    ",ans);
    68     }
    69     return 0;
    70 }
    View Code

    poj1419 Graph Coloring

    核对模版,输出最大团中的点

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=102;
     7 int ans;
     8 int x[N],tuan[N];
     9 int can[N][N];
    10 int num[N];
    11 bool g[N][N],p[N][N];
    12 int n,m;
    13 bool dfs(int tot,int cnt){
    14     int i,j,k;
    15     if(tot == 0){
    16         if(cnt > ans){
    17             ans = cnt;
    18             for(i=0;i<ans;i++){
    19                 tuan[i] = x[i];
    20             }
    21             return true;
    22         }
    23         return false;
    24     }
    25     for(i=0;i<tot;i++){
    26         if(cnt + (tot-i) <= ans)return false;
    27         if(cnt + num[can[cnt][i]] <= ans)return false;
    28         k = 0;
    29         x[cnt] = can[cnt][i];
    30         for(j=i+1;j<tot;j++){
    31             if(g[can[cnt][i]][can[cnt][j]]){
    32                 can[cnt+1][k++] = can[cnt][j];
    33             }
    34         }
    35         if(dfs(k,cnt+1))return false;
    36     }
    37     return false;
    38 }
    39 void mc(){
    40     int i,j,k;
    41     ans = 1;
    42     for(i=n;i>=1;i--){
    43         k = 0;
    44         x[0] = i;
    45         for(j=i+1;j<=n;j++){
    46             if(g[i][j]){
    47                 can[1][k++] = j;
    48             }
    49         }
    50         dfs(k,1);
    51         num[i] = ans;
    52     }
    53 }
    54 void init(){    memset(g,0,sizeof(g));memset(p,0,sizeof(p)); }
    55 
    56 int main()
    57 {
    58     //freopen("test.txt","r",stdin);
    59     int i,j,cas;
    60     scanf("%d",&cas);
    61     while(cas--)
    62     {
    63         scanf("%d%d",&n,&m);
    64         init();
    65         while(m--)
    66         {
    67             scanf("%d%d",&i,&j);
    68             p[i][j]=1;
    69         }
    70         for(i=1;i<=n;i++)
    71             for(j=1;j<=n;j++)
    72                 g[i][j]=p[i][j] ^1;
    73         mc();
    74         printf("%d
    ",ans);
    75         for(i=0;i<ans-1;i++)
    76             printf("%d ",tuan[i]);
    77         printf("%d
    ",tuan[i]);
    78     }
    79     return 0;
    80 }
    View Code

    hdu1045/zoj1002  Fire Net

    PS:记得当初,做了ZOJ第一题向按顺序试试。结果悲剧了。

    求的是最大独立集(方法挺多的)

    这是用最大团来最的代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=102;
     7 int ans;
     8 int x[N],tuan[N];
     9 int can[N][N];
    10 int num[N];
    11 bool g[N][N];
    12 int n,m;
    13 bool dfs(int tot,int cnt){
    14     int i,j,k;
    15     if(tot == 0){
    16         if(cnt > ans){
    17             ans = cnt;
    18             for(i=0;i<ans;i++){
    19                 tuan[i] = x[i];
    20             }
    21             return true;
    22         }
    23         return false;
    24     }
    25     for(i=0;i<tot;i++){
    26         if(cnt + (tot-i) <= ans)return false;
    27         if(cnt + num[can[cnt][i]] <= ans)return false;
    28         k = 0;
    29         x[cnt] = can[cnt][i];
    30         for(j=i+1;j<tot;j++){
    31             if(g[can[cnt][i]][can[cnt][j]]){
    32                 can[cnt+1][k++] = can[cnt][j];
    33             }
    34         }
    35         if(dfs(k,cnt+1))return false;
    36     }
    37     return false;
    38 }
    39 void mc(){
    40     int i,j,k;
    41     ans = 1;
    42     for(i=n*n;i>=1;i--){
    43         k = 0;
    44         x[0] = i;
    45         for(j=i+1;j<=n*n;j++){
    46             if(g[i][j]){
    47                 can[1][k++] = j;
    48             }
    49         }
    50         dfs(k,1);
    51         num[i] = ans;
    52     }
    53 }
    54 void init(){    memset(g,true,sizeof(g));}
    55 bool isin(int x, int y)
    56 {
    57     return x>=0&&x<n&&y>=0&&y<n;
    58 }
    59 int dx[4]={0,0,-1,1};
    60 int dy[4]={1,-1,0,0};
    61 char str[8][8];
    62 int main()
    63 {
    64     //freopen("test.txt","r",stdin);
    65     int i,j,k,a,b,x,y,X;
    66     while(scanf("%d",&n)!=EOF&&n)
    67     {
    68         init();
    69         getchar();
    70         for(i=0;i<n;i++) gets(str[i]);
    71         X=0;
    72         for(i=0;i<n;i++)
    73         {
    74             for(j=0;j<n;j++)
    75             {
    76                 a=i*n + j+1;
    77                 if(str[i][j]=='X'){
    78                     X++;continue;
    79                 }
    80                 for(k=0;k<4;k++)
    81                 {
    82                     x=i+dx[k]; y=j+dy[k];
    83                     while(isin(x,y)&&str[x][y]=='.')
    84                     {
    85                         b=x*n+y+1;
    86                         g[a][b]=0;
    87                         x+=dx[k]; y+=dy[k];
    88                     }
    89                 }
    90             }
    91         }
    92         mc();
    93         printf("%d
    ",ans-X);
    94     }
    95     return 0;
    96 }
    View Code

    poj1129 Channel Allocation

    染色问题中最少需要的颜色问题等价于最大团问题

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=102;
     7 int ans;
     8 int x[N],tuan[N];
     9 int can[N][N];
    10 int num[N];
    11 bool g[N][N];
    12 int n,m;
    13 bool dfs(int tot,int cnt){
    14     int i,j,k;
    15     if(tot == 0){
    16         if(cnt > ans){
    17             ans = cnt;
    18             for(i=0;i<ans;i++){
    19                 tuan[i] = x[i];
    20             }
    21             return true;
    22         }
    23         return false;
    24     }
    25     for(i=0;i<tot;i++){
    26         if(cnt + (tot-i) <= ans)return false;
    27         if(cnt + num[can[cnt][i]] <= ans)return false;
    28         k = 0;
    29         x[cnt] = can[cnt][i];
    30         for(j=i+1;j<tot;j++){
    31             if(g[can[cnt][i]][can[cnt][j]]){
    32                 can[cnt+1][k++] = can[cnt][j];
    33             }
    34         }
    35         if(dfs(k,cnt+1))return false;
    36     }
    37     return false;
    38 }
    39 void mc(){
    40     int i,j,k;
    41     ans = 1;
    42     for(i=n;i>=1;i--){
    43         k = 0;
    44         x[0] = i;
    45         for(j=i+1;j<=n;j++){
    46             if(g[i][j]){
    47                 can[1][k++] = j;
    48             }
    49         }
    50         dfs(k,1);
    51         num[i] = ans;
    52     }
    53 }
    54 void init(){    memset(g,0,sizeof(g)); }
    55 int main()
    56 {
    57     //freopen("test.txt","r",stdin);
    58     int i,j,k,cas;
    59     char ch;
    60     while(scanf("%d",&n)!=EOF&&n)
    61     {
    62         init();
    63         getchar();
    64         for(i=1;i<=n;i++)
    65         {
    66             getchar();getchar();
    67             while((ch=getchar())!='
    ')
    68             {
    69                 j=ch-64;
    70                 g[i][j]=1;
    71             }
    72         }
    73         mc();
    74         printf("%d ",ans);
    75         if(ans==1) printf("channel needed.
    ");
    76         else printf("channels needed.
    ");
    77     }
    78     return 0;
    79 }
    View Code
  • 相关阅读:
    面向对象下
    面向对象上
    将博客搬至CSDN
    矩阵的常用术语和操作
    python2.7 Unable to find vcvarsall.bat
    intellij创建maven web项目
    intellij 编译 springmvc+hibernate+spring+maven 找不到hbm.xml映射文件
    spring Thymeleaf 中文乱码
    visualstudiocode 调试electron
    android反编译工具总结
  • 原文地址:https://www.cnblogs.com/Potato-lover/p/3993984.html
Copyright © 2011-2022 走看看