[网络流24题] 分配问题 (费用流)

洛谷传送门 LOJ传送门

同样是很裸的一个费用流,模型也很好想

源点$S$向每个人连流量为$1$,费用为$0$的边,每个工作向汇点连流量为$1$,费用为$0$的边,代表每个人都只能被分配一个工作

每个人可以在所有工作中任选,而一个工作只能被完成$1$次,所以每个人$i$和每个工作$j$之间连一条流量为$1$,费用为$c_{i,j}$的边

然后上费用流就行了

  1 #include <vector>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define N1 205
  6 #define M1 50010
  7 #define ll long long
  8 #define dd double
  9 #define inf 0x3f3f3f3f
 10 using namespace std;
 11 
 12 int gint()
 13 {
 14     int ret=0,fh=1;char c=getchar();
 15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
 16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
 17     return ret*fh;
 18 }
 19 
 20 int n,nn,S,T;
 21 
 22 
 23 int flow[N1][N1],cost[N1][N1],f[N1][N1],c[N1][N1];
 24 int que[M1],hd,tl,C[N1],F[N1],pre[N1];
 25 
 26 namespace S1{
 27 void bfs()
 28 {
 29     int x,i,v;
 30     memset(C,0x3f,sizeof(C)); memset(F,0,sizeof(F)); 
 31     hd=1,tl=0; que[++tl]=S; C[S]=0; F[S]=inf;
 32     while(hd<=tl)
 33     {
 34         x=que[hd++];
 35         for(v=1;v<=nn;v++)
 36         {
 37             if(!flow[x][v]) continue; 
 38             if(C[v]>C[x]+cost[x][v]) 
 39             {
 40                 C[v]=C[x]+cost[x][v];
 41                 F[v]=min(F[x],flow[x][v]);
 42                 que[++tl]=v; pre[v]=x;
 43             }
 44         }
 45     }
 46 } 
 47 void Dinic()
 48 {
 49     memcpy(cost,c,sizeof(c)); memcpy(flow,f,sizeof(f));
 50     int cash=0,tmp,x;
 51     while(1)
 52     {
 53         bfs(); if(!F[T]) break;
 54         for(x=T;x!=S;x=pre[x]) 
 55             flow[pre[x]][x]-=F[T],flow[x][pre[x]]+=F[T];
 56         cash+=C[T]*F[T];
 57     }
 58     printf("%d\n",cash);
 59 }
 60 };
 61 
 62 namespace S2{
 63 void bfs()
 64 {
 65     int x,v;
 66     memset(C,-0x3f,sizeof(C)); memset(F,0,sizeof(F)); 
 67     hd=1,tl=0; que[++tl]=S; C[S]=0; F[S]=inf;
 68     while(hd<=tl)
 69     {
 70         x=que[hd++];
 71         for(v=1;v<=nn;v++)
 72         {
 73             if(!flow[x][v]) continue; 
 74             if(C[v]<C[x]+cost[x][v]) 
 75             {
 76                 C[v]=C[x]+cost[x][v];
 77                 F[v]=min(F[x],flow[x][v]);
 78                 que[++tl]=v; pre[v]=x;
 79             }
 80         }
 81     }
 82 } 
 83 void Dinic()
 84 {
 85     memcpy(cost,c,sizeof(c)); memcpy(flow,f,sizeof(f));
 86     int cash=0,tmp,x;
 87     while(1)
 88     {
 89         bfs(); if(!F[T]) break;
 90         for(x=T;x!=S;x=pre[x]) 
 91             flow[pre[x]][x]-=F[T],flow[x][pre[x]]+=F[T];
 92         cash+=C[T]*F[T];
 93     }
 94     printf("%d\n",cash);
 95 }
 96 };
 97 
 98 
 99 int main()
100 {
101     scanf("%d",&n); nn=n*2+2;
102     int i,j,v,ans; S=n+n+1,T=n+n+2;
103     for(i=1;i<=n;i++) for(j=1;j<=n;j++) 
104         scanf("%d",&c[i][n+j]),c[n+j][i]=-c[i][n+j],f[i][n+j]=1;
105     for(i=1;i<=n;i++) f[S][i]=1,f[n+i][T]=1;
106     S1::Dinic(); S2::Dinic();
107     return 0;
108 }

 

posted @ 2019-01-17 18:29  guapisolo  阅读(230)  评论(0编辑  收藏  举报