bzoj1458 士兵占领
Posted XD-TEST
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1458 士兵占领相关的知识,希望对你有一定的参考价值。
费用流,连下面几类边
1.s->s‘,流量为n*m,费用为0,表示最多可放置n*m个士兵
2.s‘->行
(1)流量为a[i],费用为-n*m,表示必须在这一行放置a[i]个士兵。
(2)流量为n*m,费用为0,表示该行可以放置其他任意数目士兵。
3.行->列,流量为1,费用为1,表示第i行第j列放置的士兵数目
4.列->t
(1)流量为b[i],费用为-n*m,表示必须在这一列放置b[i]个士兵。
(2)流量为n*m,费用为0,表示该列可以放置其他任意数目士兵。
5.s‘->t,流量为n*m,费用为0,表示一些士兵可以不用放置。
最后答案为费用+(Σa[i]+Σb[i])*n*m
代码
1 #include<cstdio> 2 #include<algorithm> 3 #include<queue> 4 #define mp make_pair 5 #define pii pair<int,int> 6 #define N 10010 7 #define M 200010 8 #define inf 0x37373737 9 using namespace std; 10 struct MCMF{ 11 int h[N] , dis[N] , ing[N] , pre[N] , s , t , n; 12 int to[M] , ne[M] , cap[M] , cost[M] , e; 13 void ini(){ 14 fill(h,h+N,-1); 15 e = 0; 16 } 17 void liu(int u,int v,int c,int w){ 18 to[e] = v , ne[e] = h[u] , cap[e] = c , cost[e] = w; 19 h[u] = e++; 20 } 21 void link(int u,int v,int c,int w){ 22 liu(u,v,c,w); 23 liu(v,u,0,-w); 24 } 25 bool spfa(){ 26 queue<int> Q; 27 fill(ing,ing+n,0); 28 fill(pre,pre+n,-1); 29 fill(dis,dis+n,inf); 30 ing[s] = true , dis[s] = 0; 31 Q.push(s); 32 while(!Q.empty()){ 33 int c = Q.front();Q.pop();ing[c] = false; 34 for(int k=h[c];~k;k=ne[k]){ 35 int v = to[k]; 36 if(cap[k] <= 0) continue; 37 if(dis[c] + cost[k] < dis[v]){ 38 dis[v] = dis[c] + cost[k]; 39 pre[v] = k; 40 if(!ing[v]) Q.push(v) , ing[v] = true; 41 } 42 } 43 } 44 return dis[t] != inf; 45 } 46 int flow , mincost; 47 pii run(int _s,int _t,int _n){ 48 s = _s , t = _t , n = _n; 49 flow = mincost = 0; 50 while(spfa()){ 51 int pl = inf , p , k; 52 for(p=t;p!=s;p=to[k^1]){ 53 k = pre[p]; 54 pl = min(pl,cap[k]); 55 } 56 for(p=t;p!=s;p=to[k^1]){ 57 k = pre[p]; 58 cap[k] -= pl; 59 cap[k^1] += pl; 60 } 61 mincost += pl * dis[t]; 62 flow += pl; 63 } 64 return mp(flow,mincost); 65 } 66 }; 67 MCMF t; 68 int n,m,k,i,j,a[N],b[N],sum; 69 int flag[1010][1010]; 70 int main() 71 { 72 scanf("%d%d%d",&n,&m,&k); 73 for (i=1;i<=n;i++) 74 scanf("%d",&a[i]),sum+=a[i]; 75 for (i=1;i<=m;i++) 76 scanf("%d",&b[i]),sum+=b[i]; 77 for (i=1;i<=k;i++) 78 { 79 int A,B; 80 scanf("%d%d",&A,&B); 81 flag[A][B]=1; 82 } 83 84 85 t.ini(); 86 t.link(0,n+m+1,n*m,0); 87 t.link(n+m+1,n+m+2,n*m,0); 88 for (i=1;i<=n;i++) 89 { 90 t.link(n+m+1,i,a[i],-n*m); 91 t.link(n+m+1,i,n*m,0); 92 } 93 for (i=1;i<=m;i++) 94 { 95 t.link(n+i,n+m+2,b[i],-n*m); 96 t.link(n+i,n+m+2,n*m,0); 97 } 98 for (i=1;i<=n;i++) 99 for (j=1;j<=m;j++) 100 if (flag[i][j]==0) 101 t.link(i,n+j,1,1); 102 103 int ans=t.run(0,n+m+2,n+m+10).second; 104 printf("%d\n",ans+sum*n*m); 105 }
以上是关于bzoj1458 士兵占领的主要内容,如果未能解决你的问题,请参考以下文章