【网络流24题】分配问题(二分图最佳匹配)(费用流)

【网络流24题】分配问题

题目描述 Description

有n件工作要分配给n个人做。第i 个人做第j 件工作产生的效益为ij c 。试设计一个将
n件工作分配给n个人做的分配方案,使产生的总效益最大。
«编程任务:
对于给定的n件工作和n个人,计算最优分配方案和最差分配方案。

输入描述 Input Description

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

输出描述 Output Description

将计算出的最小总效益和最大总效益输出

样例输入 Sample Input

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

样例输出 Sample Output

5
14

又是一道无数据范围的题目,无语了,开了2000

这是道裸题吧,S向左边流量为1,费用为0,

左边向右边,流量为1,费用a[i][j],

右边向汇点,流量为1,费用为0。

 

 

  1 #include<cstring>
  2 #include<cmath>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cstdio>
  6 #include<queue>
  7 
  8 #define N 2007
  9 #define M 1000007
 10 #define inf 1000000007
 11 using namespace std;
 12 inline int read()
 13 {
 14     int x=0,f=1;char ch=getchar();
 15     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
 16     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
 17     return x*f;
 18 }
 19 
 20 int n,S,T;
 21 int cnt=1,head[N],rea[M],val[M],cost[M],next[M];
 22 int dis[N],flag[N],a[N][N];
 23 struct Node
 24 {
 25     int e,fa;
 26     void init(){e=fa=-1;}
 27 }pre[N];
 28 
 29 void add(int u,int v,int fee,int pay)
 30 {
 31     next[++cnt]=head[u];
 32     head[u]=cnt;
 33     rea[cnt]=v;
 34     val[cnt]=fee;
 35     cost[cnt]=pay;
 36 }
 37 void build(int k)
 38 {
 39     cnt=1,memset(head,-1,sizeof(head));
 40     for (int i=1;i<=n;i++)
 41         add(S,i,1,0),add(i,S,0,0);
 42     for (int i=1;i<=n;i++)
 43         add(i+n,T,1,0),add(T,i+n,0,0);
 44     for (int i=1;i<=n;i++)
 45         for (int j=1;j<=n;j++)
 46             add(i,j+n,1,a[i][j]*k),add(j+n,i,0,-a[i][j]*k);        
 47 }
 48 bool Spfa()
 49 {
 50     for (int i=S;i<=T;i++)
 51         dis[i]=inf,flag[i]=0,pre[i].init();
 52     queue<int>q;q.push(S);
 53     dis[S]=0,flag[S]=1;
 54     while(!q.empty())
 55     {
 56         int u=q.front();q.pop();
 57         for (int i=head[u];i!=-1;i=next[i])
 58         {
 59             int v=rea[i],fee=cost[i];
 60             if ((dis[v]>dis[u]+fee)&&val[i]>0)
 61             {
 62                 dis[v]=dis[u]+fee;
 63                 pre[v].e=i,pre[v].fa=u;
 64                 if (!flag[v])
 65                 {
 66                     flag[v]=1;
 67                     q.push(v);
 68                 }
 69             }
 70         }
 71         flag[u]=0;
 72     }
 73     if (dis[T]==inf) return 0;
 74     else return 1;
 75 }
 76 int mfmc()
 77 {
 78     int flow=0,res=0;
 79     while(Spfa())
 80     {
 81         int x=inf;
 82         for (int i=T;pre[i].fa!=-1;i=pre[i].fa)
 83         {
 84             int e=pre[i].e;
 85             x=min(x,val[e]);
 86         }
 87         flow+=x,res+=dis[T]*x;
 88         for (int i=T;pre[i].fa!=-1;i=pre[i].fa)
 89         {
 90             int e=pre[i].e;
 91             val[e]-=x,val[e^1]+=x;
 92         }
 93     }
 94     return res;
 95 }
 96 int main()
 97 {
 98     n=read(),S=0,T=n*2+1;
 99     for (int i=1;i<=n;i++)
100         for (int j=1;j<=n;j++)
101             a[i][j]=read();
102     build(1);printf("%d\n",mfmc());
103     build(-1);printf("%d\n",-mfmc());
104 }

 

 

 

posted @ 2017-11-30 21:03  Kaiser-  阅读(545)  评论(0编辑  收藏  举报