• BZOJ 4261


    一道很不错的网络流题目...

    刚看到这题感觉无从下手,关键是要发现一个性质:对于每一个合法的方案,每一个平原块都只和与他相邻的两个平原块相连,这样我们就能够通过最大流的模型来判断是否有解了。

    那么对于带权的情况,我们考虑当前点的权值是否可以取到只取决于与当前点连接的两个平原块是否是一个方向,这样我们对一个平原块拆成2个点,分别处理X方向和Y方向,为了限制这两个方向流量和为2,我们还要再加一个点来限流,这样,如果这个2的流量是分别从X方向和Y方向流出,那么当前点的权值就能够得到,否则就不行,这个限制转化一下,变成如果当前这2个流量从一个点流出,就要花费权值的代价,那么我们可以利用费用流,通过拆边的方法进行处理,这样这个问题就解决了。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 #define M 200000
      6 #define N 20000
      7 #define NN 305
      8 int last[N],pre[M],other[M],cap[M],cost[M];
      9 int id[NN][NN],idx[NN][NN],idy[NN][NN];
     10 int n,m,tot,l,S,T,ans,flow_sum,que[M+1],dis[N],next[N];
     11 bool vis[N];
     12 
     13 inline int read(void)
     14 {
     15     int x=0;
     16     char ch=getchar();
     17     while (ch>'9'||ch<'0') ch=getchar();
     18     while (ch>='0'&&ch<='9') 
     19     {
     20         x=x*10+ch-'0';
     21         ch=getchar();
     22     }
     23     return x;
     24 }
     25 
     26 void connect(int x,int y,int z,int w)
     27 {
     28     l++;
     29     pre[l]=last[x];
     30     last[x]=l;
     31     other[l]=y;
     32     cap[l]=z;
     33     cost[l]=w;
     34     swap(x,y);
     35     l++;
     36     pre[l]=last[x];
     37     last[x]=l;
     38     other[l]=y;
     39     cap[l]=0;
     40     cost[l]=-w;
     41 }
     42 
     43 bool spfa(void) 
     44 {
     45     memset(dis,53,sizeof dis);
     46     memset(next,0,sizeof next);
     47     dis[S]=0;que[1]=S;
     48     int h=0,t=1;
     49     while (h!=t) 
     50     {
     51         h=h%M+1;
     52         int u=que[h];vis[u]=0;
     53         for (int p=last[u];p;p=pre[p])
     54         {
     55             if (cap[p]==0) continue;
     56             int v=other[p];
     57             if (dis[v]>dis[u]+cost[p]) 
     58             {
     59                 dis[v]=dis[u]+cost[p];
     60                 next[v]=p;
     61                 if (vis[v]) continue;
     62                 t=t%M+1;
     63                 que[t]=v;
     64             }
     65         }
     66     }
     67     return dis[T]<dis[0];
     68 }
     69 
     70 void MCMF(void) 
     71 {
     72     while (spfa()) 
     73     {
     74         int flow=1e9;
     75         for (int p=next[T];p;p=next[other[p^1]]) flow=min(flow,cap[p]);
     76         for (int p=next[T];p;p=next[other[p^1]]) 
     77             cap[p]-=flow,cap[p^1]+=flow;
     78         ans-=flow*dis[T];
     79         flow_sum-=flow;
     80     }
     81 }
     82 
     83 int main()
     84 {
     85     n=read();m=read();l=1;
     86     S=++tot;T=++tot;
     87     for (int i=1;i<=n;i++) 
     88         for (int j=1;j<=m;j++) 
     89         {
     90             int x=read();
     91             if (x==1) continue;
     92             flow_sum++;
     93             id[i][j]=++tot;
     94             idx[i][j]=++tot;
     95             idy[i][j]=++tot;
     96         }
     97     for (int i=1;i<=n;i++)
     98         for (int j=1;j<=m;j++) 
     99         {
    100             int x=read();
    101             if (!id[i][j]) continue;
    102             ans+=x;
    103             if ((i+j)&1) 
    104             {
    105                 connect(S,id[i][j],2,0);
    106                 connect(id[i][j],idx[i][j],1,0);
    107                 connect(id[i][j],idy[i][j],1,0);
    108                 connect(id[i][j],idx[i][j],1,x);
    109                 connect(id[i][j],idy[i][j],1,x);
    110                 if (i+1<=n&&id[i+1][j]) connect(idx[i][j],idx[i+1][j],1,0);
    111                 if (i-1>=1&&id[i-1][j]) connect(idx[i][j],idx[i-1][j],1,0);
    112                 if (j+1<=m&&id[i][j+1]) connect(idy[i][j],idy[i][j+1],1,0);
    113                 if (j-1>=1&&id[i][j-1]) connect(idy[i][j],idy[i][j-1],1,0);
    114             }
    115             else 
    116             {
    117                 connect(id[i][j],T,2,0);
    118                 connect(idx[i][j],id[i][j],1,0);
    119                 connect(idy[i][j],id[i][j],1,0);
    120                 connect(idx[i][j],id[i][j],1,x);
    121                 connect(idy[i][j],id[i][j],1,x);
    122             }
    123         }
    124     MCMF();
    125     flow_sum?puts("-1"):printf("%d
    ",ans);
    126     return 0;
    127 }
  • 相关阅读:
    理解区块链之前,先上手体验一把数字货币(2018-04-06 陈浩 第6讲)
    约瑟夫·卢宾《以太坊:从底层揭秘区块链应用和机会》2018-04-21
    以太坊智能合约介绍,Solidity介绍
    新浪微博 [异常问题] 414 Request-URL Too Large
    Google自动广告,将广告代码放置在 HTML 中的什么位置?
    囤币一族,被中国市场遗忘的价值币ADA
    基于EOS开发的Dapp大全
    朴素贝叶斯算法,贝叶斯分类算法,贝叶斯定理原理
    区块链3.0 ada Cardano卡尔达诺如何获得一致好评?
    拜占庭将军问题(Byzantine Generals Problem),一个关于分布式系统容错问题故事
  • 原文地址:https://www.cnblogs.com/lvyouyw/p/6875198.html
Copyright © 2020-2023  润新知