zoukankan      html  css  js  c++  java
  • 【bzoj4439】[Swerc2015]Landscaping 网络流最小割

    题目描述

    FJ有一块N*M的矩形田地,有两种地形高地(用‘#’表示)和低地(用‘.’表示)
    FJ需要对每一行田地从左到右完整开收割机走到头,再对每一列从上到下完整走到头,如下图所示
    对于一个4*4的田地,FJ需要走8次。
    收割机是要油的,每次从高地到低地或从低地到高地需要支付A的费用。
    但是FJ有黑科技,可以高地与低地的互变,都只需要一个支付B的费用。
    询问FJ需要支付最小费用。

    输入

    第一行包含四个整数N,M,A,B,意义如上文所述。
    接下来是一个N*M的字符串矩阵,表示农田的地形,’#’表示高地,’.’表示低地。

    输出

    只包含一个正整数,表示最小费用。
    1<=N,M<=50
    1<=A,B<=100000

    样例输入

    5 4 1000 2000
    ...#
    #..#
    ...#
    ##..
    ###.

    样例输出

    11000


    题解

    网络流最小割,和 bzoj2768/bzoj1934 差不多

    具体建图方法:S->高地,容量为B;低地->T,容量为B;x->与x相邻的点,容量为A。

    注意要连双向边(不是反向弧)

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define N 3000
    #define M 100000
    #define pos(i , j) (i - 1) * m + j
    using namespace std;
    queue<int> q;
    char str[100];
    int head[N] , to[M] , val[M] , next[M] , cnt = 1 , s , t , dis[N];
    void add(int x , int y , int z)
    {
    	to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
    	to[++cnt] = x , val[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt;
    }
    bool bfs()
    {
    	int x , i;
    	memset(dis , 0 , sizeof(dis));
    	while(!q.empty()) q.pop();
    	dis[s] = 1 , q.push(s);
    	while(!q.empty())
    	{
    		x = q.front() , q.pop();
    		for(i = head[x] ; i ; i = next[i])
    		{
    			if(val[i] && !dis[to[i]])
    			{
    				dis[to[i]] = dis[x] + 1;
    				if(to[i] == t) return 1;
    				q.push(to[i]);
    			}
    		}
    	}
    	return 0;
    }
    int dinic(int x , int low)
    {
    	if(x == t) return low;
    	int temp = low , i , k;
    	for(i = head[x] ; i ; i = next[i])
    	{
    		if(val[i] && dis[to[i]] == dis[x] + 1)
    		{
    			k = dinic(to[i] , min(temp , val[i]));
    			if(!k) dis[to[i]] = 0;
    			val[i] -= k , val[i ^ 1] += k;
    			if(!(temp -= k)) break;
    		}
    	}
    	return low - temp;
    }
    int main()
    {
    	int n , m , a , b , i , j , ans = 0;
    	scanf("%d%d%d%d" , &n , &m , &a , &b);
    	s = 0 , t = n * m + 1;
    	for(i = 1 ; i <= n ; i ++ )
    	{
    		scanf("%s" , str + 1);
    		for(j = 1 ; j <= m ; j ++ )
    		{
    			if(str[j] == '#') add(s , pos(i , j) , b);
    			else add(pos(i , j) , t , b);
    		}
    	}
    	for(i = 1 ; i <= n ; i ++ )
    	{
    		for(j = 1 ; j <= m ; j ++ )
    		{
    			if(i > 1) add(pos(i , j) , pos(i - 1 , j) , a);
    			if(i < n) add(pos(i , j) , pos(i + 1 , j) , a);
    			if(j > 1) add(pos(i , j) , pos(i , j - 1) , a);
    			if(j < m) add(pos(i , j) , pos(i , j + 1) , a);
    		}
    	}
    	while(bfs()) ans += dinic(s , 0x3f3f3f3f);
    	printf("%d
    " , ans);
    	return 0;
    }

     

  • 相关阅读:
    junit单元测试踩过的坑
    Arrays.asList()需要注意的点
    oracle数据库学习笔记
    实训笔记
    spring事务学习笔记
    java锁
    jvm内存模型
    iOS 应用架构 (三)
    iOS 应用架构 (二)
    iOS 应用架构 (一)
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6867393.html
Copyright © 2011-2022 走看看