首页 > 技术文章 > Uva1515 Pool construction

SilverNebula 2016-12-04 17:10 原文

Time Limit: 3000MS64bit IO Format: %lld & %llu

 

网络流 最小割

 

心生绝望,用了好久的网络流模板居然是错的。

↑居然之前还侥幸能过一堆(并不)题。

______

利用边容量来限制花费:

  边缘的坑必须填上,每格花费为f;

  如果一个地方id是坑,将其填上,从S到id连边,容量为f;

  如果一个地方id是草,在这挖坑,从id到T连边,容量为d;

  建立栅栏:每格向四周连边,容量为b;

↑如此建边起到了限制最小花费的作用,如果挖坑的代价比种草小,挖坑的边先流满,反之同理,求出的最小割就是达成要求的最小花费。

求最小割即可。

 

第53行 if(!f)dep[u]=0; 作用是当前路径无法扩展时,切断路径,避免重复无意义DFS。

↑以前写dinic一直不知道要加这个,居然没被卡……

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<queue>
  6 using namespace std;
  7 const int INF=1<<29;
  8 const int mxn=3500;
  9 const int mx[5]={0,1,0,-1,0};
 10 const int my[5]={0,0,1,0,-1};
 11 struct edge{
 12     int v,nxt,f;
 13 }e[100010];
 14 int hd[mxn],mct=1;
 15 int n,m,k,ans;
 16 int id[120][120];
 17 int S,T;
 18 void add_edge(int u,int v,int c){
 19     e[++mct].v=v;e[mct].nxt=hd[u];e[mct].f=c;hd[u]=mct;return;
 20 }
 21 int dep[4000];
 22 bool BFS(){
 23     queue<int>q;
 24     memset(dep,0,sizeof dep);
 25     dep[S]=1;
 26     q.push(S);
 27     while(!q.empty()){
 28         int u=q.front();q.pop();
 29         for(int i=hd[u];i;i=e[i].nxt){
 30             int v=e[i].v;
 31             if(!dep[v] && e[i].f){
 32                 dep[v]=dep[u]+1;
 33                 q.push(v);
 34             }
 35         }
 36     }
 37     return dep[T];
 38 }
 39 int DFS(int u,int lim){
 40     if(u==T) return lim;
 41     int tmp,f=0;
 42     for(int i=hd[u];i;i=e[i].nxt){
 43         int v=e[i].v;
 44         if(dep[v]==dep[u]+1 && e[i].f){
 45             tmp=DFS(v,min(lim,e[i].f));
 46             lim-=tmp;
 47             f+=tmp;
 48             e[i].f-=tmp;
 49             e[i^1].f+=tmp;
 50             if(!lim)return f;
 51         }
 52     }
 53     if(!f)dep[u]=0;
 54     return f;
 55 }
 56 int Dinic(){
 57     int res=0;
 58     while(BFS())res+=DFS(S,1e9);
 59     return res;
 60 }
 61 inline void init(){
 62     memset(hd,0,sizeof hd);
 63     for(int i=1;i<=n;i++)
 64      for(int j=1;j<=m;j++)
 65          id[i][j]=(i-1)*m+j;
 66     mct=1;
 67     ans=0;
 68     return;
 69 }
 70 int d,f,b;
 71 char mp[120][120];
 72 int main()
 73 {
 74     int cas;
 75     scanf("%d",&cas);
 76     int i,j;
 77     while(cas--){
 78         scanf("%d%d",&m,&n);
 79         scanf("%d%d%d",&d,&f,&b);
 80         init();
 81         S=0;T=n*m+2;
 82         for(i=1;i<=n;i++)scanf("%s",mp[i]+1);
 83         for(i=1;i<=n;i++)
 84             for(j=1;j<=m;j++){
 85                 if(i==1 || i==n || j==1 || j==m){
 86                     if(mp[i][j]=='.')ans+=f;
 87                     add_edge(S,id[i][j],INF);
 88                     add_edge(id[i][j],S,0);
 89                 }
 90                 else if(mp[i][j]=='#'){
 91                     add_edge(S,id[i][j],d);
 92                     add_edge(id[i][j],S,0);
 93                 }
 94                 else{
 95                     add_edge(id[i][j],T,f);
 96                     add_edge(T,id[i][j],0);
 97                 }
 98                 if(i>1){
 99                     add_edge(id[i][j],id[i-1][j],b);add_edge(id[i-1][j],id[i][j],0);
100                     add_edge(id[i][j],id[i-1][j],0);add_edge(id[i-1][j],id[i][j],b);
101                 }
102                 if(j>1){
103                     add_edge(id[i][j],id[i][j-1],b);add_edge(id[i][j-1],id[i][j],0);
104                     add_edge(id[i][j-1],id[i][j],b);add_edge(id[i][j],id[i][j-1],0);
105                 }
106             }
107         ans+=Dinic();
108         printf("%d\n",ans);
109     }
110     return 0;
111 }

 

 

推荐阅读