• 最大团问题


    最大团问题

    首先介绍一些基本概念:

    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;
    }
    
    
  • 相关阅读:
    升级xcode7.0 第三方库不能用的解决方法(bitcode是什么鬼?)
    java调用C#的dll
    微信JS SDK Demo
    【jQuery】smartMenu右键自定义上下文菜单插件(似web QQ)
    搭建Windows SVN服务器及TortoiseSVN使用帮助和下载
    微信jsSDK开发
    用c#开发微信(10) JSSDK 基本用法 分享接口“发送到朋友”
    MVC4.0网站发布和部署到IIS7.0上的方法
    C#的事件处理机制
    ASP.Net MVC开发基础学习笔记(1):走向MVC模式
  • 原文地址:https://www.cnblogs.com/JohnRan/p/13220055.html
Copyright © 2020-2023  润新知