UVA1515 Pool construction (最小割模型)

如果不允许转化'#'和'.'的话,那么可以直接在'#'和'.'之间连容量为b的边,把所有'#'和一个源点连接,

所有'.'和一个汇点连接,流量不限,那么割就是建围栏(分割'#'和'.')的花费。

问题是'#'和'.'是可以转化的,由刚才的思路,可以联想到,当'#'可以转化成'.'的时候,那么就不需要在它和周围的'.'之间建围栏,

那么可以限制源点到'#'的容量为d,表示最多花费为d,对称地,限制'.'到汇点T容量为f。

然后跑最大流最小割就好了。

MinCut

这题思路好神啊。。。仔细体会容量表示最多花费和最小割的关系

#include<bits/stdc++.h>
using namespace std;

struct Edge
{
    int v,cap,nxt;
};
const int maxv = 2502+6;
vector<Edge> edges;
#define PB push_back
int head[maxv],cur[maxv];

void AddEdge(int u,int v,int c)
{
    edges.PB({v,c,head[u]});
    head[u] = edges.size()-1;
    edges.PB({u,0,head[v]});
    head[v] = edges.size()-1;
}

int S = 0,T = 1;
int lv[maxv];
bool vis[maxv];
int q[maxv];

bool bfs()
{
    memset(vis,0,sizeof(vis));
    int l = 0, r = 0;
    lv[S] = 0; q[r++] = S; vis[S] = true;
    while(r>l){
        int u = q[l++];
        for(int i = head[u]; ~i; i = edges[i].nxt){
            Edge &e = edges[i];
            if(!vis[e.v] && e.cap){
                lv[e.v] = lv[u]+1; vis[e.v] = true;
                q[r++] = e.v;
            }
        }
    }
    return vis[T];
}

int dfs(int u,int a)
{
    if(u == T||!a) return a;
    int flow = 0,f;
    for(int  &i = cur[u]; ~i; i = edges[i].nxt){
        Edge &e = edges[i];
        if(lv[e.v] == lv[u]+1 && (f = dfs(e.v,min(a,e.cap)))){
            flow += f;
            e.cap -= f;
            edges[i^1].cap += f;
            a -= f;
            if(!a) break;
        }
    }
    return flow;
}

const int INF = 0x3f3f3f3f;
int MaxFlow()
{
    int flow = 0;
    while(bfs()){
        memcpy(cur,head,sizeof(head));
        flow += dfs(S,INF);
    }
    return flow;
}


const int N = 50;
char g[N][N+2];
int id[N][N];
int h,w;
int d,f,b;

int ID(int i,int j) { return i*w+j+2; }

void init()
{
    scanf("%d%d%d%d%d",&w,&h,&d,&f,&b);
    edges.clear();
    for(int i = 0; i < h; i++){
        scanf("%s",g[i]);
        for(int j = 0; j < w; j++){
            id[i][j] = ID(i,j);
        }
    }
     memset(head,-1,sizeof(head));
}
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};


int main()
{
    //freopen("in.txt","r",stdin);
    int TestCase; scanf("%d",&TestCase);
    while(TestCase--){
        init();
        int cost = 0;
        for(int i = 0; i < h; i++){
            for(int j = 0; j < w; j++){
                if(i == 0 || i == h-1 || j == 0|| j == w-1){
                    if(g[i][j] == '.') cost += f;
                    AddEdge(S,id[i][j],INF);
                }else {
                    if(g[i][j] == '#') AddEdge(S,id[i][j],d);
                    else AddEdge(id[i][j],T,f);
                }
                for(int k = 0; k < 4; k++){
                    int ni = i+dx[k], nj = j+dy[k];
                    if(ni<0||ni>=h||nj<0||nj>=w) continue;
                    AddEdge(id[i][j],id[ni][nj],b);
                }
            }
        }
        printf("%d\n",cost+MaxFlow());
    }
    return 0;
}

 

posted @ 2015-08-26 22:49  陈瑞宇  阅读(1397)  评论(1编辑  收藏  举报