nefu485分配问题(二分图的最佳匹配)
来源:互联网 发布:java交换两个变量的值 编辑:程序博客网 时间:2024/05/29 01:55
分配问题
Time Limit 1000ms
Memory Limit 65536K
description
有n件工作要分配给n个人做。第i 个人做第j 件工作产生的效益为ij c 。试设计一个将n件工作分配给n个人做的分配方案,使产生的总效益最大。 对于给定的n件工作和n个人,计算最优分配方案和最差分配方案。
input
多组数据输入.每组输入第1 行有1 个正整数n<=50,表示有n件工作要分配给n 个人做。接下来的n 行中,每行有n 个整数Cij,1≤i≤n,1≤j≤n,表示第i 个人做第j件工作产生的效益为Cij 。
output
每组输出的最小总效益和最大总效益。
sample_input
52 2 2 1 22 3 1 2 42 0 1 1 12 3 4 3 33 2 1 2 1
sample_output
514
二分图最佳匹配就是在满足匹配数最大的情况下,使费用取得最值的一类问题二分图最佳匹配其实是费用流的一个特例,我们只要在原图中增加一个源点和汇点就成功的转换成费用流
模型,其转换方式与二分图最大匹配转最大流一样,新增加的边的费用都为0
#include <iostream>#include <cstdio>using namespace std;const int oo=1e5;const int mm=11111;const int mn=888;int node,src,dest,edge,SC[mn][mn];int ver[mm],flow[mm],cost[mm],next[mm];int head[mn],dis[mn],p[mn],q[mn],vis[mn];void prepare(int _node,int _src,int _dest){ node=_node,src=_src,dest=_dest; for(int i=0;i<node;++i)head[i]=-1,vis[i]=0; edge=0;}void addedge(int u,int v,int f,int c){ ver[edge]=v,flow[edge]=f,cost[edge]=c,next[edge]=head[u],head[u]=edge++; ver[edge]=u,flow[edge]=0,cost[edge]=-c,next[edge]=head[v],head[v]=edge++;}bool spfa(){ int i,u,v,l,r=0,tmp; for(i=0;i<node;i++) dis[i]=oo; dis[q[r++]=src]=0; p[src]=p[dest]=-1; for(l=0;l!=r;(++l>=mn)?l=0:l) for(i=head[u=q[l]],vis[u]=0;i>=0;i=next[i]) if(flow[i]&&dis[v=ver[i]]>(tmp=dis[u]+cost[i])) { dis[v]=tmp;//cout<<"u="<<u<<" v="<<v<<" tmp="<<tmp<<endl; p[v]=i^1; if(vis[v]) continue; vis[q[r++]=v]=1; if(r>=mn) r=0; } return p[dest]>-1;}bool spfa1(){ int i,u,v,l,r=0,tmp; for(i=0;i<node;i++) dis[i]=-oo; dis[q[r++]=src]=0; p[src]=p[dest]=-1; for(l=0;l!=r;(++l>=mn)?l=0:l) for(i=head[u=q[l]],vis[u]=0;i>=0;i=next[i]) if(flow[i]&&dis[v=ver[i]]<(tmp=dis[u]+cost[i])) { dis[v]=tmp;//cout<<"u="<<u<<" v="<<v<<" tmp="<<tmp<<endl; p[v]=i^1; if(vis[v]) continue; vis[q[r++]=v]=1; if(r>=mn) r=0; } return p[dest]>-1;}int Spfaflow(){ int i,ret=0,delta; while(spfa()) { for(i=p[dest],delta=oo;i>=0;i=p[ver[i]]){ if(flow[i^1]<delta) delta=flow[i^1];} // cout<<"delta="<<delta<<endl; for(i=p[dest];i>=0;i=p[ver[i]]) flow[i]+=delta,flow[i^1]-=delta; ret+=delta*dis[dest];//cout<<"ret="<<ret<<endl; } return ret;}int SpfaFlow(){ int i,ret=0,delta; while(spfa1()) { for(i=p[dest],delta=oo;i>=0;i=p[ver[i]]){ if(flow[i^1]<delta) delta=flow[i^1];} // cout<<"delta="<<delta<<endl; for(i=p[dest];i>=0;i=p[ver[i]]) flow[i]+=delta,flow[i^1]-=delta; ret+=delta*dis[dest];//cout<<"ret="<<ret<<endl; } return ret;}int main(){ int n,tot,i,j,a; while(~scanf("%d",&n)) { prepare(2*n+2,0,2*n+1); for(i=1;i<=n;i++){ addedge(0,i,1,0); // cout<<"from=0 to="<<i<<endl; } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { scanf("%d",&SC[i][j]); addedge(i,n+j,oo,SC[i][j]); // cout<<"from="<<i<<" to="<<n+j<<" a="<<a<<endl; } } for(i=1;i<=n;i++){ addedge(n+i,2*n+1,1,0); // cout<<"from="<<n+i<<" to="<<2*n+1<<endl; } printf("%d\n",Spfaflow()); prepare(2*n+2,0,2*n+1); for(i=1;i<=n;i++){ addedge(0,i,1,0); //cout<<"from=0 to="<<i<<endl; } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { addedge(i,n+j,oo,SC[i][j]); //cout<<"from="<<i<<" to="<<n+j<<" a="<<a<<endl; } } for(i=1;i<=n;i++){ addedge(n+i,2*n+1,1,0); //cout<<"from="<<n+i<<" to="<<2*n+1<<endl; } printf("%d\n",SpfaFlow()); } return 0;}
- nefu485分配问题(二分图的最佳匹配)
- 十八、分配问题 [二分图最佳匹配]
- 分配问题 二分最佳匹配问题
- [网络流24题] 18 分配问题(二分图最佳匹配,最小费用最大流)
- 二分图的最佳匹配
- pku2195二分图的最佳匹配问题mub
- 二分图最佳匹配
- 线性规划与网络流24题之分配问题 最大费用最大流、最小费用最大流、二分图的最佳匹配
- 二分图的最佳匹配(KM 算法)
- 二分图的最佳匹配(KM 算法)
- 带权二分图的最佳匹配(KM算法)
- KM算法 二分图的最佳匹配
- 二分图的最佳匹配(KM 算法)
- 【二分图最佳匹配】丘比特的烦恼
- poj2195 二分图的最佳匹配
- 二分图最佳匹配(网络流)
- 二分图最佳匹配 入门
- 二分图最佳匹配 题目
- 腾讯QQ中批量删除好友的方法
- poj 2828 Buy Tickets
- 人生会重复,也会循环
- STL学习笔记(三) 堆的操作
- Qt XML读取写入操作
- nefu485分配问题(二分图的最佳匹配)
- 【数据结构及算法】2.图像染色问题
- SQL Server建立用户并分配权限
- 多表处理(四)-函数
- 用C#编程修改Word模版
- WinJS.Class 初探
- Windows程序设计的三本经典的书籍
- 笔试题四+答案
- 原型模式