赞
踩
定义:
二分图:一个图被分成了两部分,相同的部分没有边
匹配:二分图G的子图M中,M的边集{E}中的任意两条边都不指向同一个顶点
极大匹配:在当前已完成的匹配下,无法再通过增加未完成匹配的边的方式来增加匹配的边数
最大匹配:是所有极大匹配当中边数最大的一个匹配
完全匹配(完备匹配):一个匹配中,图中的每个顶点都和图中某条边相关联
有什么用:
定理1:最小点覆盖数 = 最大匹配数
点覆盖:点集合使得任意一条边至少有一个端点在集合中
定理2:最大独立集 = 顶点数 - 最大匹配数
独立集:点集合中任何两个顶点都不互相连接
定理3:最小路径覆盖数 = 顶点数 – 最大匹配数
路径覆盖:任何一个点都属于且仅属于一条路径
代码实现:(匈牙利算法)
匈牙利算法与交错路
#include<iostream> #include<vector> #include<cstring> using namespace std; vector<int> g[1005]; int n,m,e; int link[1005],cnt; int vis[1005]; int find(int x){ for(int i=0;i<g[x].size();i++){ int u=g[x][i]; if(!vis[u]){ vis[u]=1; if(link[u]==0||find(link[u])){ link[u]=x; return 1; } } } return 0; } int main(){ cin>>n>>m>>e; int x,y; for(int i=1;i<=e;i++){ cin>>x>>y; if (x>=1&&y>=1&&x<=n&&y<=m) g[x].push_back(y); } for(int i=1;i<=n;i++){ memset(vis,0,sizeof(vis)); if(find(i)) cnt++; } cout<<cnt; return 0; }
时间复杂度:
O(nm) 其中n是点数,m是边数
但事实上,对于绝大部分的二分图,匈牙利算法都跑不够上限
题目:
定理证明:http://www.cnblogs.com/jasonlixuetao/p/4756026.html
题意:有一个N*N的网格,该网格有K个障碍物.你有一把武器,每次你使用武器可以清楚该网格特定行或列的所有障碍.问你最少需要使用多少次武器能清除网格的所有障碍物?
/*把网格的行1到N看成左边点集的点,网格的列号看成右边点集的点 如果(i,j)格有障碍,那么就在左边i点到右边j点之间连接一条边 接下来求最小点覆盖数即可*/ #include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn=500+10; int n; vector<int> g[maxn]; int vis[maxn]; int link[maxn]; int find(int u) { for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(!vis[v]) { vis[v]=1; if(!link[v]||find(link[v])){ link[v]=u; return 1; } } } return 0; } int main(){ int n,k; scanf("%d%d",&n,&k); while(k--) { int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); } int ans=0; for(int i=1;i<=n;i++){ memset(vis,0,sizeof(vis)); if(find(i)) ans++; } printf("%d\n",ans); return 0; }
定理证明:最大独立集=顶点数-最小顶点覆盖数=顶点数-最大匹配数
题意:动物园有若干只狗和猫,每个小朋友都要么喜欢一只狗不喜欢一只猫,要么反过来。现在要移除一些狗和猫,小朋友只有在不移除自己喜欢的动物,移除了自己不喜欢的动物才会开心。问最多能让几个小朋友开心。
/*把人当作节点,矛盾的人连边,做最大独立集*/
#include<iostream>
#include<cstdio>
#include<cstring>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。