UVA Live 6129 (Codeforces Gym 100642H) Sofa, So Good 最小费用流

来源:互联网 发布:手机验证码php源码 编辑:程序博客网 时间:2024/06/13 12:34

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=573&page=show_problem&problem=4140


Sofia’s Sofa Salon specializes in synthesizing and supplying spectacular specialty sofas. heir manufacturingprocess has been couched in mystery until recently, when it was revealed that the creation ofa sofa is divided into two phases: framing and upholstering. When an order for a set of sofas comesin, the management team uses their knowledge of how quickly any particular worker can frame anygiven sofa to decide which worker will frame which sofa so as to minimize the total time spent framing.Management always ensures there are exactly enough workers on the job to handle the order beingfilled, and each worker can frame only one sofa per order (due to a recurring series of repetitive motioninjury claims).

Once the workers have begun framing, management performs an analysis of the upholstering phaseknowing the time it takes each worker to upholster any given sofa. They must assign each workerexactly one sofa to upholster (potentially different from the one they framed) when they finish theirframing. A worker may have to wait until the sofa they are assigned to upholster is finished beingframed by another worker, so they start work on it once it’s available. If they are idle between theframing and upholstering phases they usually relax in the company’s recreational facility where theyplay tag (this room is called the chase lounge). Management tried to stop them from playing this game,but they were stymied by a sign reading “Do not remove this tag.”

Since the workers are paid by the hour whether they are working or playing tag, management wouldlike to assign them sofas to upholster so as to minimize the total number of hours that the workers areon-site (given the framing assignment determined earlier and the fact that each worker leaves as soonas they finish upholstering). Management is not prepared to solve such a deep-seated problem, so theyhave requested that you furnish a program to help them


工厂里生产沙发需要经过两个步骤,现在n个人生产n个沙发,每个人负责一个沙发的第一步骤和一个沙发的第二步骤。每个沙发必须先经过第一步骤的加工再来到第二步骤。给你每个人生产每个沙发的两个步骤的时间,问你怎么安排使每个人在第一第二步骤的总间隙时间最少。


如果没有两个步骤,这就是最小费用流模板题。

加了一个步骤,我们可以求两次费用流。其中,第一次每条边的费用就是第一步骤花费的时间,第二次每条边的费用是在选择了第一次费用流所确定的方案后,再执行第二个步骤的两部分的总时间。

这样求两次费用流之后,就能得到答案。


#include <cstdio>#include <iostream>#include <string.h>#include <string> #include <map>#include <queue>#include <vector>#include <set>#include <algorithm>#include <math.h>#include <cmath>#include <bitset>#define mem0(a) memset(a,0,sizeof(a))#define meminf(a) memset(a,0x3f,sizeof(a))using namespace std;typedef long long ll;typedef long double ld;const int maxn=205,maxk=5005,inf=0x3f3f3f3f;  const ll llinf=0x3f3f3f3f3f3f3f3f;   const ld pi=acos(-1.0L); int a[maxn][maxn],b[maxn][maxn];int path[maxn],rflow[maxn],inque[maxn],dist[maxn];int head[maxn],ans1[maxn],ans2[maxn],ans3[maxn],k[maxn];string s;int num; struct Edge {int from,to,cost,flow,pre;};Edge edge[maxk*2];void addedge(int s,int t,int cost,int flow) {edge[num]=(Edge){s,t,cost,flow,head[s]};head[s]=num++;edge[num]=(Edge){t,s,-cost,0,head[t]};head[t]=num++;}int spfa(int s,int t) {mem0(inque);meminf(dist);memset(path,-1,sizeof(path));memset(rflow,-1,sizeof(rflow));queue<int> q;    q.push(s);    inque[s]=1;    int i;    dist[s]=0;    rflow[s]=inf;    while (!q.empty()) {    int now=q.front();    q.pop();    inque[now]=0;    for (i=head[now];i!=-1;i=edge[i].pre) {    int to=edge[i].to;    if (edge[i].flow>0&&dist[now]+edge[i].cost<dist[to]) {    dist[to]=dist[now]+edge[i].cost;    path[to]=i;    rflow[to]=min(rflow[now],edge[i].flow);if (!inque[to]) {inque[to]=1;q.push(to);}    }    }    }    if (dist[t]==inf) return 0; else return dist[t];}int mincostmaxflow(int s,int t) {int f,sum=0,now;while (f=spfa(s,t)) {now=path[t];while (now!=-1) {//int i=now;//cout << edge[i].from << ' ' << edge[i].to << ' ' << edge[i].cost << ' ' << edge[i].flow << ' ' << endl;   edge[now].flow-=rflow[t];edge[now^1].flow+=rflow[t];now=path[edge[now].from];//cout << edge[i].from << ' ' << edge[i].to << ' ' << edge[i].cost << ' ' << edge[i].flow << ' ' << endl;}sum+=f;}return sum;}int main (){int n,qwe=0;scanf("%d",&n);while (n!=0) {qwe++;int i,j;num=0;memset(head,-1,sizeof(head));for (i=1;i<=n;i++) {for (j=1;j<=n;j++) {scanf("%d",&a[i][j]);addedge(i,j+n,a[i][j],1);}}for (i=1;i<=n;i++) {addedge(0,i,0,1);addedge(i+n,2*n+1,0,1);}int ans=mincostmaxflow(0,2*n+1);int cnt=0;for (i=1;i<=n;i++) {for (j=1;j<=n;j++) {if (edge[cnt].flow==0) ans1[i]=j,k[j]=i;cnt+=2;}}num=0;memset(head,-1,sizeof(head));for (i=1;i<=n;i++) {for (j=1;j<=n;j++) {scanf("%d",&b[i][j]);addedge(i,j+n,max(a[i][ans1[i]],a[k[j]][j])+b[i][j],1);}}for (i=1;i<=n;i++) {addedge(0,i,0,1);addedge(i+n,2*n+1,0,1);}ans=mincostmaxflow(0,2*n+1);cnt=0;for (i=1;i<=n;i++) {for (j=1;j<=n;j++) {if (edge[cnt].flow==0) ans2[i]=j,ans3[i]=edge[cnt].cost;cnt+=2;}}int sum=0;printf("Case %d:\n",qwe);for (i=1;i<=n;i++) {printf("Worker %d: %d %d %d\n",i,ans1[i],ans2[i],ans3[i]);sum+=ans3[i]-a[i][ans1[i]]-b[i][ans2[i]];}printf("Total idle time: %d\n",sum);scanf("%d",&n);}return 0;}