• 【bzoj5070】危险的迷宫 费用流


    题目描述

    JudgeOnline/upload/201710/55.doc

    输入

    第一行是两个整数A与B(1≤A,B≤10),中间用空格分隔,表示该迷宫是A行B列的。
    第2行至第A+1行,每行有B个1至100以内的整数,表示该迷宫每一格的危险程度。
    以下一行是一个整数K。接着K行每行有四个整数X0,Y0,X1,Y1,
    (1 ≤X0,X1≤A, 1≤Y0,Y1≤B) ,(X0,Y0),(X1,Y1)为相邻的两格,这两格相通。
    接着一行是一个整数N(0≤N≤A*B/2),表示有N个出口与入口。
    以下N行,每行有两个整数X0,Y0,表示每个入口的行列位置。
    以下还有N行,每行有两个整数X1,Y1,表示每个出口的行列位置。

    输出

    输出仅一个数,若队员们不能全部到达指定目标位置,则输出-1;
    否则输出所有队员所经过的所有单元格的危险程度之和。

    样例输入

    3 4
    20 30 40 30
    30 60 20 20
    20 15 20 20
    13
    1 1 2 1
    1 2 1 3
    1 2 2 2
    1 3 1 4
    1 4 2 4
    2 1 2 2
    2 1 3 1
    2 2 2 3
    2 3 2 4
    2 4 3 4
    3 1 3 2
    3 2 3 3
    3 3 3 4
    2
    1 1
    1 2
    2 3
    3 4

    样例输出

    235


    题解

    费用流

    这题意真的不知道怎么概括了。。。

    A、B只有10,一眼网络流;再想一下就很容易想出费用流建模。

    建图方法:

    把每个点拆成入点和出点两个,中间连边,容量为1,费用为对应代价;

    对于相邻的点x、y,从x的出点向y的入点、从y的出点向x的入点连边,容量为1,费用为0;

    对于起点,源点向其连边,容量为1,费用为0;对于终点,其向汇点连边,容量为1,费用为0。

    跑费用流,如果满流则说明有解,输出费用;否则无解。

    切掉0AC并拿下rank1真开心 (*^▽^*)

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #define N 300
    #define M 10000
    #define pos(i , j , k) (k * n * m + (i - 1) * m + j)
    using namespace std;
    queue<int> q;
    int head[N] , to[M] , val[M] , cost[M] , next[M] , cnt = 1 , s , t , dis[N] , from[N] , pre[N];
    inline void add(int x , int y , int v , int c)
    {
    	to[++cnt] = y , val[cnt] = v , cost[cnt] = c , next[cnt] = head[x] , head[x] = cnt;
    	to[++cnt] = x , val[cnt] = 0 , cost[cnt] = -c , next[cnt] = head[y] , head[y] = cnt;
    }
    bool spfa()
    {
    	int x , i;
    	memset(from , -1 , sizeof(from));
    	memset(dis , 0x3f , sizeof(dis));
    	dis[s] = 0 , 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[x] + cost[i])
    				dis[to[i]] = dis[x] + cost[i] , from[to[i]] = x , pre[to[i]] = i , q.push(to[i]);
    	}
    	return ~from[t];
    }
    int main()
    {
    	int n , m , k , p , i , j , a , b , c , d , flow = 0 , ans = 0;
    	scanf("%d%d" , &n , &m) , s = 0 , t = n * m * 2 + 1;
    	for(i = 1 ; i <= n ; i ++ )
    		for(j = 1 ; j <= m ; j ++ )
    			scanf("%d" , &a) , add(pos(i , j , 0) , pos(i , j , 1) , 1 , a);
    	scanf("%d" , &k);
    	for(i = 1 ; i <= k ; i ++ ) scanf("%d%d%d%d" , &a , &b , &c , &d) , add(pos(a , b , 1) , pos(c , d , 0) , 1 , 0) , add(pos(c , d , 1) , pos(a , b , 0) , 1 , 0);
    	scanf("%d" , &p);
    	for(i = 1 ; i <= p ; i ++ ) scanf("%d%d" , &a , &b) , add(s , pos(a , b , 0) , 1 , 0);
    	for(i = 1 ; i <= p ; i ++ ) scanf("%d%d" , &a , &b) , add(pos(a , b , 1) , t , 1 , 0);
    	while(spfa())
    	{
    		flow ++ , ans += dis[t];
    		for(i = t ; i != s ; i = from[i]) val[pre[i]] -- , val[pre[i] ^ 1] ++ ;
    	}
    	if(flow < p) puts("-1");
    	else printf("%d
    " , ans);
    	return 0;
    }
    

     

  • 相关阅读:
    会计基础-资本与资本公积核算
    FORM 基本控件2
    EBS form的一些知识
    EBS功能安全性基本原理
    主物料界面数据来源
    organization --form 表单中organization 数据来源
    form 相关
    jar/war/ear文件的区别
    ORACLE判别字段是否包含中文
    亲测可用:SecureCRT 7 注册码/序列号
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7715228.html
Copyright © 2020-2023  润新知