zoukankan      html  css  js  c++  java
  • UVa 1515 Pool construction (最小割)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=528&page=show_problem&problem=3916

    题目大意:给定一个h*w的矩阵,每格是草地(#)或洞(.),可以花费d把一个#变成.,也可以花费f把一个.变成#,最后相邻的#和.之间要隔一个栅栏,每个花费为b.最后边界上必须全部是#,求最少花费.

    分析:- - 感觉不容易想到...首先由分隔开#和.以及花费最少,联想到最小割.设置一个s,一个t,s连所有#,权重为d,若#变成.,即把这个点分到T中去,需要把这条边割断;所有.连到t,权重为f;相邻点互相连一条边,权重为b,最后如果一个在S一个在T,则需要把这条边割断.还有边界需要是草地,故把s连到边界,权值设为无穷.最后求一下从s到t的最小割即可.

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<queue>
     6 typedef long long ll;
     7 using namespace std;
     8 const int maxn=2550,maxm=25500,INF=1000000;
     9 int w,h,d,f,b;
    10 
    11 struct Edge{
    12     int from,to,cap,flow;
    13     Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
    14 };
    15 
    16 struct EdmondsKarp{
    17     int n,m;
    18     vector<Edge> edges;
    19     vector<int> G[maxn];
    20     int p[maxn],a[maxn];
    21 
    22     void init(int _n){
    23         this->n=n;
    24         this->m=0;
    25         for(int i=0;i<maxn;i++)G[i].clear();
    26         edges.clear();
    27     }
    28 
    29     void AddEdge(int from,int to,int cap,int flow){
    30         edges.push_back(Edge(from,to,cap,flow));
    31         edges.push_back(Edge(to,from,0,flow));
    32         G[from].push_back(m++);
    33         G[to].push_back(m++);
    34     }
    35 
    36     ll Maxflow(int s,int t){
    37         ll flow=0;
    38         while(1){
    39             memset(a,0,sizeof(a));
    40             queue<int>Q;
    41             Q.push(s);
    42             a[s]=INF;
    43             while(!Q.empty()){
    44                 int x=Q.front();Q.pop();
    45                 for(int i=0;i<G[x].size();i++){
    46                     Edge &e=edges[G[x][i]];
    47                     if(!a[e.to]&&e.cap>e.flow){
    48                         p[e.to]=G[x][i];
    49                         a[e.to]=min(a[x],e.cap-e.flow);
    50                         Q.push(e.to);
    51                     }
    52                 }
    53                 if(a[t])break;
    54             }
    55             if(!a[t])break;
    56             for(int u=t;u!=s;u=edges[p[u]].from){
    57                 edges[p[u]].flow+=a[t];
    58                 edges[p[u]^1].flow-=a[t];
    59             }
    60             flow+=a[t];
    61         }
    62         return flow;
    63     }
    64 };
    65 
    66 int main(){
    67     int kase;
    68     long long ans=0;
    69     cin>>kase;
    70     while(kase--){
    71         ans=0;
    72         cin>>w>>h;
    73         cin>>d>>f>>b;
    74         EdmondsKarp ek;
    75         ek.init(w*h+2);
    76         char c;
    77         for(int i=0;i<w*h;i++){
    78             cin>>c;
    79             if(i/w==0||i/w==h-1||i%w==0||i%w==w-1){
    80                 if(c!='#')ans+=f;
    81                 ek.AddEdge(w*h,i,INF,0);
    82             }
    83             else if(c=='#')ek.AddEdge(w*h,i,d,0);
    84             else ek.AddEdge(i,w*h+1,f,0);
    85             if(i>0&&(i-1)/w==i/w)ek.AddEdge(i,i-1,b,0);
    86             if(i<w*h&&(i+1)/w==i/w)ek.AddEdge(i,i+1,b,0);
    87             if(i-w>=0)ek.AddEdge(i,i-w,b,0);
    88             if(i+w<w*h)ek.AddEdge(i,i+w,b,0);
    89         }
    90         ans+=ek.Maxflow(w*h,w*h+1);
    91         cout<<ans<<endl;
    92     }
    93     return 0;
    94 }
  • 相关阅读:
    【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)
    【POJ 2152】 Fire (树形DP)
    【POJ 1741】 Tree (树的点分治)
    【POJ 2486】 Apple Tree (树形DP)
    【HDU 3810】 Magina (01背包,优先队列优化,并查集)
    【SGU 390】Tickets (数位DP)
    【SPOJ 2319】 BIGSEQ
    【SPOJ 1182】 SORTBIT
    【HDU 5456】 Matches Puzzle Game (数位DP)
    【HDU 3652】 B-number (数位DP)
  • 原文地址:https://www.cnblogs.com/7391-KID/p/6880268.html
Copyright © 2011-2022 走看看