zoukankan      html  css  js  c++  java
  • 二分图 (最大匹配 + 最小点覆盖 + 最少路径覆盖 + 最大独立集)

    最大匹配

    匈牙利算法。

    最小点覆盖

    概念:用最少的点,让每条边都至少和其中的一个点关联

    König定理:一个二分图中的最大匹配数等于该图的最小顶点覆盖数。 

    最小点覆盖 = 最大匹配。

    证明:这里

    最少路径覆盖(不相交路径)

    概念:在一个有向图中,找出最少的路径,使得这些路径经过其中每个点,且每个点只与一条路径相关联。

    方法:最少路径覆盖 = 点数 - 二分图最大匹配 。

    证明:设点数为 n ,最大匹配数为 m,因为我们要让路径尽量少,先设每个点即一条路径,然后一个匹配可以连接两个点,即两个点变成了一条路径,也就是 n - 1,有 m 个匹配,也就是还剩下 n - m 条路径

    最少路径覆盖(可相交路径)

    方法:首先用 floyd 求出原图的传递闭包,然后如果 a -> b 有边且原图无边,则进行加边,最后化为 不相交路径的最少路径覆盖。

    最大独立集

    概念:在有N个点的图中,找出 m 个点,是这m个点两两之间的没有边。m 的最大值。

    方法:最大独立集 = 点数 - 最小点覆盖 。  

    证明:我们可以先把所有点放入集合中,现在要去找最少的点使所有的边都被删完,这就是最小点覆盖,因此只要让点数减去最小点覆盖就是最大独立集。

     染色+匈牙利模板

    #include<bits/stdc++.h>
    #define ll long long
    #define MOD 998244353 
    #define INF 0x3f3f3f3f
    #define mem(a,x) memset(a,x,sizeof(a))  
    #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    using namespace std;
    
    const int NUM = 1e5+5;
    int n,m,e,flag,ans;
    int link[NUM];
    bool vis[NUM];
    int col[NUM];
    vector<int>g[4*NUM];
    bool dfs(int x)
    {
    	for(int i=0;i<g[x].size();i++){
    		int v=g[x][i];
    		if(!vis[v]){
    			vis[v]=1;
    			if(!link[v]||dfs(link[v])){
    				link[v]=x;
    				return true;
    			}
    		}
    	}
    	return false;
    }
    void ran(int x,int color)    //染色法判断是否是二分图
    {
    	if(flag==0)return;
    	col[x]=color;
    	for(int i=0;i<g[x].size();i++){
    		if(col[g[x][i]]==col[x]){
    			flag=0;
    			return;
    		}
    		if(!col[g[x][i]]){
    			ran(g[x][i],-color);
    		}
    	}
    }
    int main()
    {
    	while(~scanf("%d %d",&n,&m)){
    		mem(link,0);
    	    mem(vis,0);
    	    mem(col,0);
    	    for(int i=1;i<=n;i++){
    	    	g[i].clear();
    	    }
            for(int i=1;i<=m;i++){
            	int a,b;
            	scanf("%d %d",&a,&b);
            	g[a].push_back(b);
            	g[b].push_back(a);
            }
            flag=1;
            for(int i=1;i<=n&&flag;i++){    //非连通图特有
                if(!col[i]){                //
                	ran(i,1);               //
                }                           //
            }                               //
            ans=0;
            if(flag==0){
            	cout<<"No"<<endl;
            }
            if(flag){
            	for(int i=1;i<=n;i++){
            		if(col[i]==1){
            			for(int j=1;j<=n;j++){
            			    if(col[j]==-1){
            				   vis[j]=0;
            			    }
            		    }
            			//cout<<i<<endl;
            			if(dfs(i)){
            				ans++;
            				//cout<<i<<endl;
            			}
            		}
            	}
            	cout<<ans<<endl;
            }
    	}
        return 0;
    }
    越自律,越自由
  • 相关阅读:
    用 Python 带你看各国 GDP 变迁
    Fluent Interface(流式接口)
    probing privatePath如何作用于ASP.NET MVC View
    Word插入htm文件导致文本域动态增加的一个问题
    Visual Studio 2013附加进程调试IE加载的ActiveX Control无效解决方法
    Ubuntu下Chrome运行Silverlight程序
    Windows Phone Bing lock screen doesn't change解决方法
    SPClaimsUtility.AuthenticateFormsUser的证书验证问题
    Web Service Client使用Microsoft WSE 2.0
    Visual Studio 2013安装Update 3启动crash的解决方法
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/13435558.html
Copyright © 2011-2022 走看看