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 士兵占领的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1458: 士兵占领 -- 最大流

BZOJ-1458士兵占领 最大流

bzoj1458: 士兵占领 网络流

bzoj1458士兵占领

bzoj 1458: 士兵占领

BZOJ1458: 士兵占领