zoukankan      html  css  js  c++  java
  • 图论常见结论

    图论常见结论

    二分图:

    最大匹配:二分图中一个边的集合{E}中,当任意两条边都不相交于同一个节点时,这个边集被称作一个匹配,这个集合最大时,称为一个最大匹配。

    最小点覆盖:如果选定一个点,看做选择了它连接的所有边,能涵盖所有边时且节点最少时,称为最小点覆盖。

    最大独立集:选出一些点,使得它们两两没有边连接。选择的点最多时,这个集合称作最大独立集。

    总点数=最小点覆盖+最大独立集证明

    最小点覆盖=最大匹配( König定理)。从右边未匹配的点出发,沿着未匹配-匹配-未匹配去dfs。最终最小点覆盖就是左边出现的点和右边未出现的点。

    最小边覆盖=点数-最大匹配。

    无向图:

    最大独立集=补图的最大团,反之亦然。

    例题:传送门

    分析,首先要考虑连续的1是没用的,其次,两个1之间的这些条件没办法同时满足。如果建模成图论,往两个点之间连边,要选出一个独立集出来。借用上面的结论,那就是求一个补图的最大团。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 45;
    
    int nd, nm, G[N][N];
    int cntClique, pts[N], res[N], cnt[N];
    
    map<string, int> H;
    
    int n;
    
    vector<int> v;
    
    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(){
        ios_base::sync_with_stdio(0);
        cin.tie(0);
    
        memset(G,1,sizeof G);
    
        cin>>nd>>nm;
        for(int i=1;i<=nd;++i){
            int op;string s;
            cin>>op;
            if(op==1){
                v.clear();
            }else{
                cin>>s;
                if(!H.count(s)){
                    H[s]=++n;
                }
                /*n^2建图跑的飞起,cf数据有问题*/
                int y=H[s];
                for(auto& x:v){
                    G[x][y]=0;
                    G[y][x]=0;
                }
                v.push_back(y);
            }
        }
    
        maxClique();
        if(cntClique<0){
            cout<<"0";
        }else{
            cout<<cntClique;
        }
        return 0;
    }
    
    
  • 相关阅读:
    织梦开发——相关阅读likeart应用
    织梦标签教程
    织梦专题调用代码
    HIT 2543 Stone IV
    POJ 3680 Intervals
    HIT 2739 The Chinese Postman Problem
    POJ 1273 Drainage Ditches
    POJ 2455 Secret Milking Machine
    SPOJ 371 Boxes
    HIT 2715 Matrix3
  • 原文地址:https://www.cnblogs.com/JohnRan/p/13576881.html
Copyright © 2011-2022 走看看