Libre 6012 「网络流 24 题」分配问题 (网络流,费用流)
2017-08-08 11:54
447 查看
Libre 6012 「网络流 24 题」分配问题 (网络流,费用流)
Description
有n件工作要分配给n个人做。第i个人做第j件工作产生的效益为\(c_{ij}\)。试设计一个将n件工作分配给n个人做的分配方案,使产生的总效益最大。对于给定的n件工作和n个人,计算最优分配方案和最差分配方案。
Input
第1 行有1 个正整数n,表示有n件工作要分配给n 个人做。接下来的n 行中,每行有n 个整数\(c_{ij}\),1≤i≤n,1≤j≤n,表示第i 个人做第j件工作产生的效益为\(c_{ij}\)。
Output
将计算出的最小总效益和最大总效益输出Sample Input
52 2 2 1 2
2 3 1 2 4
2 0 1 1 1
2 3 4 3 3
3 2 1 2 1
Sample Output
514
Http
Libre:https://loj.ac/problem/6012Source
网络流,费用流解决思路
此题的网络流做法还是比较明显的。对于每一个人,从源点连边容量为1代价为0,而对于每一项工作,连到汇点容量为1,代价为0。对于每一个\(c_{ij}\),连接人i和工作j,容量为1代价为\(c_{ij}\)。然后分别跑最小费用最大流和最大费用最大流即可。代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int maxN=300; const int maxM=maxN*maxN*4; const int inf=2147483647; class Edge { public: int u,v,cost,flow; }; int n; int cnt=-1; int Head[maxN]; int Next[maxM]; Edge E[maxM]; int Dist[maxN]; bool inqueue[maxN]; int Q[maxM]; int Path[maxN]; int Flow[maxN]; int G[maxN][maxN]; void Add_Edge(int u,int v,int cost,int flow); bool spfa1(); bool spfa2(); int main() { scanf("%d",&n); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%d",&G[i][j]); //Q1最小费用最大流 cnt=-1; memset(Head,-1,sizeof(Head)); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) Add_Edge(i,j+n,G[i][j],1); for (int i=1;i<=n;i++) { Add_Edge(0,i,0,1); Add_Edge(i+n,n*2+1,0,1); } int Ans=0; while (spfa1()) { int now=n*2+1; int last=Path[now]; while (now!=0) { E[last].flow-=Flow[n*2+1]; E[last^1].flow+=Flow[n*2+1]; now=E[last].u; last=Path[now]; } Ans+=Dist[n*2+1]*Flow[n*2+1]; } cout<<Ans<<endl; //Q2最大费用最大流 cnt=-1; memset(Head,-1,sizeof(Head)); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) Add_Edge(i,j+n,G[i][j],1); for (int i=1;i<=n;i++) { Add_Edge(0,i,0,1); Add_Edge(i+n,n*2+1,0,1); } Ans=0; while (spfa2()) { int now=n*2+1; int last=Path[now]; while (now!=0) { E[last].flow-=Flow[n*2+1]; E[last^1].flow+=Flow[n*2+1]; now=E[last].u; last=Path[now]; } Ans+=Dist[n*2+1]*Flow[n*2+1]; } cout<<Ans<<endl; return 0; } void Add_Edge(int u,int v,int cost,int flow) { cnt++; Next[cnt]=Head[u]; Head[u]=cnt; E[cnt].u=u; E[cnt].v=v; E[cnt].cost=cost; E[cnt].flow=flow; cnt++; Next[cnt]=Head[v]; Head[v]=cnt; E[cnt].u=v; E[cnt].v=u; E[cnt].flow=0; E[cnt].cost=-cost; } bool spfa1() { for (int i=0;i<=n*2+1;i++) Dist[i]=inf; memset(inqueue,0,sizeof(inqueue)); int h=1,t=0; Q[1]=0; inqueue[0]=1; Dist[0]=0; Flow[0]=inf; do { t++; int u=Q[t]; inqueue[u]=0; for (int i=Head[u];i!=-1;i=Next[i]) { int v=E[i].v; if ((E[i].flow>0)&&(Dist[v]>Dist[u]+E[i].cost)) { Dist[v]=Dist[u]+E[i].cost; Flow[v]=min(Flow[u],E[i].flow); Path[v]=i; if (inqueue[v]==0) { h++; Q[h]=v; inqueue[v]=1; } } } } while (h!=t); if (Dist[n*2+1]==inf) return 0; return 1; } bool spfa2() { for (int i=0;i<=n*2+1;i++) Dist[i]=-inf; memset(inqueue,0,sizeof(inqueue)); int h=1,t=0; Q[1]=0; inqueue[0]=1; Dist[0]=0; Flow[0]=inf; do { t++; int u=Q[t]; inqueue[u]=0; for (int i=Head[u];i!=-1;i=Next[i]) { int v=E[i].v; if ((E[i].flow>0)&&(Dist[v]<Dist[u]+E[i].cost)) { Dist[v]=Dist[u]+E[i].cost; Flow[v]=min(Flow[u],E[i].flow); Path[v]=i; if (inqueue[v]==0) { h++; Q[h]=v; inqueue[v]=1; } } } } while (h!=t); if (Dist[n*2+1]==-inf) return 0; return 1; }
相关文章推荐
- LOJ6012「网络流 24 题 - 13」分配问题 坠小费用坠大流 坠大费用坠大流
- 线性规划与网络流24题之分配问题 最大费用最大流、最小费用最大流、二分图的最佳匹配
- 【网络流24题】分配问题 最小最大费用最大流
- loj6012「网络流 24 题」分配问题(费用流)
- 【网络流24题】分配问题(费用流)
- 【网络流24题】No.18 分配问题 (二分图最佳匹配 费用流|KM)
- 740. [网络流24题] 分配问题 费用流/求最大最小费用
- Libre 6009 「网络流 24 题」软件补丁 / Luogu 2761 软件安装问题 (最短路径,位运算)
- Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流)
- 【网络流24题】航空线路问题(费用流)
- loj6012「网络流 24 题」分配问题
- [网络流24题] 分配问题
- 【网络流24题】No.21 (最长 k 可重区间集问题 最长不相交路径 最大费用流)
- 线性规划与网络流24题の18 分配问题(最小费用最大流、最大费用最大流)
- 【网络流24题】航空路线问题(最大费用流)
- loj6011「网络流 24 题」运输问题(费用流)
- 【费用流】【网络流24题】【cogs 739】运输问题
- [网络流24题] 餐巾计划问题 [费用流]
- [网络流24题] 18 分配问题(二分图最佳匹配,最小费用最大流)
- 【网络流24题】No.16 数字梯形问题 (不相交路径 最大费用流)