洛谷 P4014:「分配问题」

洛谷 P4014:「分配问题」

题目链接

题目描述

有n件工作要分配给n个人做.第i个人做第j件工作产生的效益为Cij .试设计一个将n件工作分配给n个人做的分配方案,使产生的总效益最大.

输入格式

文件的第1行有1个正整数n,表示有n件工作要分配给n个人做. 接下来的n行中,每行有n个整数Cij ,表示第i个人做第j件工作产生的效益为Cij .

输出格式

两行分别输出最小总效益和最大总效益。

输入输出样例

样例输入

5
2 2 2 1 2
2 3 1 2 4
2 0 1 1 1
2 3 4 3 3
3 2 1 2 1

样例输出

5
14

说明/提示

1≤ n100 一个人只能修一个工件

这是一道费用流经典题目

 建图       

1.设0为超级源点,2*n+1为超级汇点,第i个人的节点为i,第j件工作节点为j+n

2.从超级源点 向任意 i 属于[1,n] 连接一条容量为1,费用为0的边

3.从任意 j 属于 [n+1,2*n] 向超级汇点连接一条容量为1,费用为0的边

4.从任意 i 属于 [1,n]向 任意 j 属于 [n+1,n*2],连接一条容量为1,费用为Ci,j 的边

做法

跑一遍最小费用最大流&最大费用最小流,然后再分别输出最小值与最大值 (温馨提醒:一定要输出,不然会WA!)

为各位大佬献上我丑陋的代码~

  1 #include<bits/stdc++.h>
  2 #define FQ(i,a,b) for(register int i=a;i<=b;i++)
  3 #define prf printf
  4 #define scf scanf
  5 #define ll long long
  6 using namespace std;
  7 const int N=5e4+10;
  8 int INF,n,num=1,ne[N],fi[N],to[N],w[N],pl[N],S,T;
  9 int dst[N],incf[N],P[N],vis[N],ans;
 10 queue<int> q;
 11 void FindMaxN()
 12 {
 13     int fINDmAXn[1];
 14     memset(fINDmAXn,128/2,sizeof(fINDmAXn));    
 15     INF=fINDmAXn[0];
 16 }
 17 ll read()
 18 {
 19     ll x=0,f=1;char ch=getchar();
 20     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 21     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 22     return x*f; 
 23 }
 24 void add(int x,int y,int z,int kl)
 25 {
 26     ne[++num]=fi[x];    
 27     fi[x]=num;    
 28     to[num]=y;   
 29     w[num]=z;
 30     pl[num]=kl; 
 31 }
 32 bool spfa()
 33 { 
 34     for(int i=S;i<=T;i++)dst[i]=INF; 
 35     memset(vis,0,sizeof(vis));  
 36     q.push(S),dst[S]=0; 
 37     incf[S]=1<<30,vis[S]=true;   
 38     while(!q.empty())
 39     {      
 40         int x=q.front();      
 41         vis[x]=false;q.pop();        
 42         for(int i=fi[x];i;i=ne[i])
 43         {            
 44             int ver=to[i];             
 45             if(dst[ver]>dst[x]+pl[i]&&w[i])
 46             {                
 47                 dst[ver]=dst[x]+pl[i];                
 48                 incf[ver]=min(incf[x],w[i]);                
 49                 P[ver]=i;                
 50                 if(!vis[ver])vis[ver]=true,q.push(ver);                 
 51             }             
 52         }    
 53     }
 54     return dst[T]!=INF;  
 55 }
 56 void update()
 57 {   
 58     int x=T;     
 59     while(x!=S)
 60     {         
 61         int i=P[x];         
 62         w[i]-=incf[T];       
 63         w[i^1]+=incf[T];
 64 
 65         x=to[i^1];
 66     }
 67     ans+=dst[T]*incf[T];
 68 }
 69 bool spfa_d()
 70 {
 71     for(int i=S;i<=T;i++)dst[i]=-INF;
 72     q.push(S),dst[S]=0;incf[S]=1<<30;
 73     while(!q.empty())
 74     {
 75         int x=q.front();
 76         vis[x]=false;q.pop();
 77         for(int i=fi[x];i;i=ne[i])
 78         {
 79             int ver=to[i];
 80             if(dst[ver]<dst[x]+pl[i]&&w[i])
 81             {
 82                 dst[ver]=dst[x]+pl[i];
 83                 incf[ver]=min(incf[x],w[i]);
 84                 P[ver]=i;
 85                 if(!vis[ver])vis[ver]=true,q.push(ver);
 86             }
 87         }
 88     }
 89     return dst[T]!=-INF;
 90 }
 91 void update_d()
 92 {
 93     int x=T;
 94     while(x!=S)
 95     {
 96         int i=P[x];
 97         w[i]-=incf[T];
 98         w[i^1]+=incf[T];
 99         x=to[i^1];
100     }
101     ans+=dst[T]*incf[T];
102 }
103 void add_x(int x,int y,int z,int kl)
104 {
105     add(x,y,z,kl);
106     add(y,x,0,-kl);
107 }
108 int main()
109 {
110     //freopen(".in","r",stdin);
111     //freopen(".out","w",stdout);
112     FindMaxN();
113     n=read();S=0,T=n*2+1;
114     for(int i=1;i<=n;i++)
115     {
116         for(int j=1;j<=n;j++)
117         {
118             int x=read();
119             add_x(i,j+n,1,x);
120         }
121     }
122     for(int i=1;i<=n;i++)add_x(S,i,1,0),add_x(i+n,T,1,0);
123     while(spfa())update();
124     printf("%d
",ans);
125     ans=0;
126     for(int i=2;i<=num;i+=2)w[i]+=w[i^1],w[i^1]=0;
127     while(spfa_d())update_d();
128     printf("%d
",ans);
129     return 0;       
130 }
131 //**月雩·薇嫭**

by:月雩·薇嫭

 

原文地址:https://www.cnblogs.com/yueyuweihu/p/12093052.html