zoukankan      html  css  js  c++  java
  • 【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
  • 相关阅读:
    4.2说说计算机中的异常
    1.1组合电路、时序电路在计算机课程中的地位
    EFM32JG系列MCU内部温度传感器使用方法
    +7虚拟内存的作用,通过什么方式提高虚拟内存的性能
    +6存储结构是怎样提高性能的,它和局部性的关系是什么。
    +5性能分析定律
    +4 高速缓存
    +3软件优化至关重要,软件优化一般有哪些方法?
    +2流水线是怎样提高性能的,会遇到什么问题,解决方法是什么
    +1阿姆达尔定律
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9305525.html
Copyright © 2011-2022 走看看