[网络流24题] 分配问题 (费用流)
同样是很裸的一个费用流,模型也很好想
源点$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 }