图论总结(10)二分图匹配
来源:互联网 发布:张伯礼 知乎 编辑:程序博客网 时间:2024/05/21 17:37
二分图匹配都能用网络流来解决,但代码太复杂。
先是简单的最大匹配(无权):
KM死磕了很久才看懂。
直接匈牙利:
模板:
//int S[maxn];int T[maxn];int Left[maxn];int m,n;//int Right[maxn];bool match(int i){for(int j=1;j<=n;j++)if(!T[j]&&G[i][j]){T[j]=true;if(!Left[j]||match(Left[j])){Left[j]=i;return true;}}return false ;}void KM(){memset(Left,0,sizeof(Left));int ans=0;for(int i=1;i<=m;i++){memset(T,0,sizeof(T));if(match(i))ans++;}cout<<ans;}
最大权匹配以及完美匹配
找了一个网上得模板,感觉比蓝书上的好
模板:
#include<iostream>#include<cstring>using namespace std;const int maxn=101;const int INF=0x3f3f3f3f;int lx[maxn],ly[maxn];bool S[maxn],T[maxn];int n,Left[maxn],w[maxn][maxn],Right[maxn];bool match(int i){S[i]=true;for(int j=1;j<=n;j++)if(!T[j]&&w[i][j]==lx[i]+ly[j]){T[j]=true;if(!Left[j]||match(Left[j])){Left[j]=i;Right[i]=j;return true;}}return false ;}void KM(){for(int i=1;i<=n;i++){Left[i]=lx[i]=ly[i]=Right[i]=0;for(int j=1;j<=n;j++)lx[i]=max(lx[i],w[i][j]);}for(int i=1;i<=n;i++){for(;;){memset(S,0,sizeof(S));memset(T,0,sizeof(T));if(match(i))break;int a=INF;for(int i=1;i<=n;i++)if(S[i])for(int j=1;j<=n;j++)if(!T[j])a=min(lx[i]+ly[j]-w[i][j],a);for(int i=1;i<=n;i++){if(S[i])lx[i]-=a;if(T[i])ly[i]+=a;}}}int ans=0;for(int i=1;i<=n;i++)if(w[i][Right[i]]>0)ans+=w[i][Right[i]];cout<<ans;}int main(){freopen("in.txt","r",stdin);cin>>n;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){cin>>w[i][j];if(!w[i][j])w[i][j]=-INF;}KM();}
match函数和上面是一样的。
模板二(用slack优化):
#include<iostream>#include<cstring>using namespace std;const int maxn=101;const int INF=0x3f3f3f3f;int Left[maxn],T[maxn],S[maxn];int w[maxn][maxn];int lx[maxn],ly[maxn];int slack[maxn],n;int match(int i){S[i]=true;for(int j=1;j<=n;j++)if(!T[j]){if(lx[i]+ly[j]==w[i][j]){T[j]=true;if(!Left[j]||match(Left[j])){Left[j]=i;return true;}}else slack[j]=min(slack[j],lx[i]+ly[j]-w[i][j]);}return false ;}void KM(){for(int i=1;i<=n;i++){Left[i]=lx[i]=ly[i]=0;for(int j=1;j<=n;j++)lx[i]=max(w[i][j],lx[i]);}for(int i=1;i<=n;i++){memset(slack,INF,sizeof(slack));for(;;){memset(S,0,sizeof(S));memset(T,0,sizeof(T));if(match(i))break;int a=INF;for(int i=1;i<=n;i++)if(!T[i])a=min(a,slack[i]);for(int i=1;i<=n;i++){if(S[i])lx[i]-=a;if(T[i])ly[i]+=a;}}}int ans=0;for(int i=1;i<=n;i++)if(w[Left[i]][i]>0)ans+=w[Left[i]][i];cout<<ans;}int main(){freopen("in.txt","r",stdin);cin>>n;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){cin>>w[i][j];if(!w[i][j])w[i][j]=-INF;}KM();}
阅读全文
1 0
- 图论总结(10)二分图匹配
- 二分图匹配总结
- 二分图匹配总结
- 二分图匹配总结
- 二分图匹配总结
- 二分图匹配总结
- 二分图匹配总结
- 二分图匹配总结
- 二分图匹配总结
- 二分图匹配算法总结(转)
- 二分图最大匹配总结(转)
- 二分图匹配算法总结
- 二分图最大匹配总结
- 二分图匹配算法总结
- 二分图匹配算法总结
- 二分图匹配算法总结
- [转载]二分图匹配总结
- 二分图匹配算法总结
- android集成pdf显示与批注注释功能
- 迭代器失效问题讲解
- ASP.NET Core 运行原理解剖[1]-Hosting
- 关于物联网
- 交叉编译lis3dh
- 图论总结(10)二分图匹配
- hdu 6172 矩阵快速幂 找规律
- listview双联动
- LinkedList与ArrayList区别
- Redis源码剖析--跳跃表
- KindEditor 自定义插件:实现在内容编辑器中选中任意一张图片将其设置为文章封面缩略图
- Magic Bracelet POJ
- 如何为网站配置(Let’s Encrypt)HTTPS协议
- java编程分享