• 【UVA1515 算法竞赛入门指南】 水塘【最小割】


    题意:

      输入一个h行w列的字符矩阵,草地用“#”表示,洞用"."表示。你可以把草改成洞,每格花费为d,也可以把洞填上草,每格花费为f。最后还需要在草和洞之间修围栏,每条边花费为b。整个矩阵第一行/列和最后一行列必须是草。求最小花费。

    分析

      这是一个最小割的很典型的题目。

      每个洞要么是草地,要么是洞,我们假设草地是S集合,洞是Y集合,然后洞和草之间要建栅栏,也就可以理解为,用最少的花费将S集合和Y集合分开,这就是最小割的模型了。初始时,从s点向所有的草地点连一条边,容量为d,割这些边意味着将这个草地变成洞。把每个洞的点向t连一条边,容量为f,割这些边意味着将这个洞变成草。相邻的两个格子之间u和v,连两条边,u到v和 v到u,容量为b。割u到v这条边意味着u是草,v是洞,在之间建围栏。割v到u的点也类似。

     题目还有一个要求,矩阵第一行/列和最后一行/列必须是草,所以,s向这些草连边容量为INF,代表这些边不能割。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <iostream>
      5 #include <queue>
      6 
      7 using namespace std;
      8 const int maxn=3000+10;
      9 const int maxw=55;
     10 const int maxm=30000;
     11 const int INF=2147000000;
     12 struct Dinic{
     13     int head[maxn],Next[maxm],to[maxm],cap[maxm],flow[maxm];
     14     int sz,n,m,s,t;
     15     bool vis[maxn];
     16     int cur[maxn],d[maxn];
     17     void init(int n){
     18         this->n=n;
     19         memset(head,-1,sizeof(head));
     20         sz=-1;
     21     }
     22     void add_edge(int a,int b,int c){
     23         ++sz;
     24         to[sz]=b;
     25         cap[sz]=c;flow[sz]=0;
     26         Next[sz]=head[a];head[a]=sz;
     27         ++sz;
     28         to[sz]=a;
     29         cap[sz]=c;flow[sz]=c;
     30         Next[sz]=head[b];head[b]=sz;
     31     }
     32     bool BFS(){
     33         memset(vis,0,sizeof(vis));
     34         queue<int>Q;
     35         vis[s]=1;
     36         d[s]=0;
     37         Q.push(s);
     38         while(!Q.empty()){
     39             int u=Q.front();Q.pop();
     40             for(int i=head[u];i!=-1;i=Next[i]){
     41                 int v=to[i];
     42                 if(!vis[v]&&cap[i]>flow[i]){
     43                     vis[v]=1;
     44                     d[v]=d[u]+1;
     45                     Q.push(v);
     46                 }
     47             }
     48         }
     49         return vis[t];
     50    }
     51     int DFS(int x,int a){
     52         if(x==t||a==0)return a;
     53         int Flow=0,f;
     54         for(int& i=cur[x];i!=-1;i=Next[i]){
     55             int v=to[i];
     56             if(d[v]==d[x]+1&&(f=DFS(v,min(a,cap[i]-flow[i])))>0){
     57                 Flow+=f;
     58                 flow[i]+=f;
     59                 flow[i^1]-=f;
     60                 a-=f;
     61                 if(a==0)break;
     62             }
     63         }
     64         return Flow;
     65     }
     66     int Maxflow(int s,int t){
     67         this->s=s,this->t=t;
     68         int Flow=0;
     69         while(BFS()){
     70             for(int i=0;i<=n;i++)
     71              cur[i]=head[i];
     72             Flow+=DFS(s,INF);
     73         }
     74         return Flow;
     75     }
     76 }dinic;
     77 int w,h,d,f,b,T,ans;
     78 char G[maxw][maxw];
     79 int main(){
     80     scanf("%d",&T);
     81     for(int t=1;t<=T;t++){
     82         ans=0;
     83         scanf("%d%d",&w,&h);
     84         scanf("%d%d%d",&d,&f,&b);
     85         for(int i=1;i<=h;i++){
     86             for(int j=1;j<=w;j++){
     87                 scanf(" %c",&G[i][j]);
     88                 if(i==1||j==1||i==h||j==w){
     89                     if(G[i][j]=='.'){
     90                         G[i][j]='#';
     91                         ans+=f;
     92                     }
     93                 }
     94             }
     95         }
     96         dinic.init(w*h+2);
     97         for(int i=1;i<=h;i++){
     98             for(int j=1;j<=w;j++){
     99                 if(i==1||j==1||i==h||j==w){
    100                     dinic.add_edge(0,(i-1)*w+j,INF);
    101                 }else{
    102                     if(G[i][j]=='#'){
    103                         dinic.add_edge(0,(i-1)*w+j,d);
    104                     }
    105                     if(G[i][j]=='.'){
    106                         dinic.add_edge((i-1)*w+j,h*w+1,f);
    107                     }
    108                 }
    109                 if(i+1<=h){
    110                     dinic.add_edge((i-1)*w+j,i*w+j,b);
    111                     dinic.add_edge(i*w+j,(i-1)*w+j,b);
    112                 }
    113                 if(j+1<=w){
    114                     dinic.add_edge((i-1)*w+j,(i-1)*w+j+1,b);
    115                     dinic.add_edge((i-1)*w+j+1,(i-1)*w+j,b);
    116                 }
    117             }
    118         }
    119         ans+=dinic.Maxflow(0,w*h+1);
    120         printf("%d
    ",ans);
    121     }
    122 return 0;
    123 }
    View Code
  • 相关阅读:
    C#深入浅出 修饰符(二)
    HDU 5785 Interesting
    HDU 5783 Divide the Sequence
    HDU 5781 ATM Mechine
    UVA 714 Copying Books
    uva 1471 Defense Lines
    UVA 11134 Fabled Rooks
    UVA 11572 Unique Snowflakes
    UVA 11093 Just Finish it up
    UVA 10954 Add All
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9305525.html
Copyright © 2020-2023  润新知