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

    最大团问题

    首先介绍一些基本概念:

    1、什么是团?如果一个子图是一个无向图的完全子图,那么可以称为一个团。

    2、什么是极大团?如果一个团不是任何一个团的子集,那么可以称做一个极大团。

    3、如果一个极大团的大小是最大的,那么可以被称为一个最大团。

    最大团有以下常见性质,这里不加证明的直接给出结论。

    最大团点的数量等于其补图中最大独立集的数量(最大团与最大独立集的关系)。特别的,在二分图中,最大独立集=顶点数-最大匹配数。(这个很好理解,因为找到补图中的最大团,在图中这些边都是不存在的,并且是点个数最多的。)

    下面给出模板:(HDU 1530)

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 105;
    
    int n, G[N][N];
    int cntClique, pts[N], res[N], cnt[N];
    
    bool dfs(int pos, int num){
    
        for(int i=pos+1;i<=n;++i){
            if(cnt[i]+num<=cntClique)return false;//这里是一处剪枝
    
            if(G[pos][i]){//考虑与当前团节点的关系
                int ok=1;
                for(int id=1;id<=num;++id){
                    if(!G[i][pts[id]]){
                        ok=0;break;
                    }
                }
    
                if(ok){
                    pts[num+1]=i;
                    if(dfs(i,num+1))return true;
                }
            }
        }
    
        if(num>cntClique){ //多枚举一个,最多只扩充一个点
            for(int i=1;i<=num;++i){
                res[i]=pts[i];
            }
            cntClique=num;
            return true;
        }
    
        return false;
    }
    
    void maxClique(){
        cntClique=-1;
        for(int i=n;i>0;--i){
            pts[1]=i;
            dfs(i,1);
            cnt[i]=cntClique;
        }
    }
    
    int main(){
        while(scanf("%d",&n)&&n){
            memset(G,0,sizeof G);
            for(int i=1;i<=n;++i){
                for(int j=1;j<=n;++j){
                    scanf("%d",&G[i][j]);
                }
            }
    
            maxClique();
            printf("%d
    ",cntClique);
        }
        return 0;
    }
    

    POJ(1419)

    #include<cstdio>
    #include<cstring>
    
    //#include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 105;
    
    int n, m, G[N][N];
    int cntClique, pts[N], res[N], cnt[N];
    
    bool dfs(int pos, int num){
    
        for(int i=pos+1;i<=n;++i){
            if(cnt[i]+num<=cntClique)return false;//这里是一处剪枝
    
            if(G[pos][i]){//考虑与当前团节点的关系
                int ok=1;
                for(int id=1;id<=num;++id){
                    if(!G[i][pts[id]]){
                        ok=0;break;
                    }
                }
    
                if(ok){
                    pts[num+1]=i;
                    if(dfs(i,num+1))return true;
                }
            }
        }
    
        if(num>cntClique){ //多枚举一个,最多只扩充一个点
            for(int i=1;i<=num;++i){
                res[i]=pts[i];
            }
            cntClique=num;
            return true;
        }
    
        return false;
    }
    
    void maxClique(){
        cntClique=-1;
        for(int i=n;i>0;--i){
            pts[1]=i;
            dfs(i,1);
            cnt[i]=cntClique;
        }
    }
    
    int main(){
        int T;scanf("%d",&T);
        while(T--){
            memset(G,0,sizeof G);
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;++i){
                int u,v;scanf("%d%d",&u,&v);
                G[u][v]=1;G[v][u]=1;
            }
    
            for(int i=1;i<=n;++i){
                for(int j=1;j<=n;++j){
                    if(i==j)G[i][j]=0;
                    else{
                        G[i][j]^=1;
                    }
                }
            }
    
            maxClique();
            printf("%d
    ",cntClique);
            for(int i=1;i<=cntClique;++i){
                printf("%d ",res[i]);
            }
    
        }
        return 0;
    }
    
    
  • 相关阅读:
    使用python脚本自动创建pip.ini配置文件
    Windows 安全软件集
    配置 vim 编辑器
    (转)linux下和云端通讯的例程, ubuntu和openwrt实验成功(一)
    转 10 个最佳的 Node.js 的 MVC 框架
    转-基于NodeJS的14款Web框架
    (转) [it-ebooks]电子书列表
    (原创) alljoyn物联网实验之手机局域网控制设备
    (原创)天气又转热了,我给她做了个智能小风扇
    Alljoyn瘦客户端库介绍(官方文档翻译 下)
  • 原文地址:https://www.cnblogs.com/JohnRan/p/13220055.html
Copyright © 2011-2022 走看看