二分图最大匹配
来源:互联网 发布:八爪鱼数据导出破解 编辑:程序博客网 时间:2024/05/22 05:49
讲解:
http://www.renfei.org/blog/bipartite-matching.html
补充定义和定理:
最大匹配数:最大匹配的匹配边的数目
最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择
最大独立数:选取最多的点,使任意所选两点均不相连
最小路径覆盖数:对于一个 DAG(有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径。路径长可以为 0(即单个点)。
定理1:最大匹配数 = 最小点覆盖数(这是 Konig 定理)
定理2:最大匹配数 = 最大独立数
定理3:最小路径覆盖数 = 顶点数 - 最大匹配数
手工模板:
http://paste.ubuntu.com/12192113/
//#include<bits/stdc++.h>#include <cstdio>#include <cstdlib>#include <iostream>#include <cstring>#include <string>#include <vector>#include <cmath>#include <map>#include <queue>#include <stack>#include <set>#include <algorithm>using namespace std;#define For(i,a,b) for(int (i)=(a);(i) < (b);(i)++)#define rof(i,a,b) for(int (i)=(a);(i) > (b);(i)--)#define IOS ios::sync_with_stdio(false)#define lson l,m,rt <<1#define rson m+1,r,rt<<1|1#define mem(a,b) memset(a,b,sizeof(a))typedef long long ll;typedef unsigned long long ull;void RI (int& x){ x = 0; char c = getchar (); while (c == ' '||c == '\n') c = getchar (); bool flag = 1; if (c == '-'){ flag = 0; c = getchar (); } while (c >= '0' && c <= '9'){ x = x * 10 + c - '0'; c = getchar (); } if (!flag) x = -x;}void RII (int& x, int& y){RI (x), RI (y);}void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}/**************************************END define***************************************/const int maxn = 2e3+10;//单侧顶点最大数目const int INF =0x3f3f3f3f;const int maxm = 2e4+10;struct Side{ int from,to,next;};struct BPM{ int n,m; //左右n,m个点 Side side[maxm]; int top; int node[maxn]; int left[maxn]; // left[i]为右边第i个点的匹配点编号,-1表示不存在 bool T[maxn]; // T[i]为右边第i个点是否已标记 /*求最小覆盖点集时用 int right[maxn]; // right[i]为左边第i个点的匹配点编号,-1表示不存在 bool S[maxn]; //左边第i个点,被标记为true时:为未盖点 */ void init(int nn,int mm) { n=nn,m=mm; top=0; mem(node,-1); } void add_side(int u,int v) { side[top]=(Side){u,v,node[u]}; node[u]=top++; } bool dfs(int u){ /*S[u]=true;*/ for(int i=node[u];i!=-1;i=side[i].next){ int v=side[i].to; if(!T[v]){ T[v]=true; if(left[v]==-1||dfs(left[v])){ left[v]=u; /*right[u]=v;*/ return true; } } } return false; } //求最大匹配,匈牙利算法 int hungarian() { int ans=0; mem(left,-1); /*mem(right,-1);*/ // u 范围为0~n-1 for(int u=0;u<n;u++){ /*mem(S,0);*/ mem(T,0); if(dfs(u)) ans++; } return ans; } /* //求最小覆盖。X和Y为最小覆盖中的点集 int mincover(vector<int>& X,vector<int>& Y){ int ans=hungarian(); mem(S,0); mem(T,0); for(int u=0;u<n;u++) if(right[u]==-1) dfs(u);// 从所有X未盖点出发增广 for(int u=0;u<n;u++) if(!S[u]) X.push_back(u);//S[u]为false为匹配点 for(int v=0;v<m;v++) if(T[v])Y.push_back(v);//T[u]为true为匹配点 return ans; } */};BPM solver;int main(){ freopen("input.txt","r",stdin); int n,m; while(~scanf("%d%d",&n,&m)){ solver.init(n,n); while(m--){ int x,y; RII(x,y); x--;y--; solver.add_side(x,y); } int ans=solver.hungarian(); printf("%d\n",ans); } return 0;}
0 0
- 二分图最大匹配
- 二分图最大匹配 。
- 二分图最大匹配
- 二分图最大匹配
- 二分图最大匹配
- 二分图最大匹配
- 二分图 最大匹配
- 二分图最大匹配
- 二分图最大匹配
- 二分图最大匹配
- 二分图最大匹配
- 二分图最大匹配
- 二分图最大匹配
- 二分图最大匹配
- 二分图最大匹配
- 二分图最大匹配
- 二分图 最大匹配
- 二分图最大匹配
- 输出单层结点
- java多线程之三
- UML总结(对九种图的认识和如何使用Rational Rose 画图)
- Android笔记 4
- QT与Visual Studio 2010整合的例子
- 二分图最大匹配
- Java并发编程:Lock
- cookie 和session 的区别详解
- VLAD局部特征聚合描述符
- linux网络编程4:客户端和服务端的聊天
- c++加密解密
- ifreq
- struct和typedef struct分析
- 按钮双虚线框的问题原因及解决