P4001 [ICPC-Beijing 2006]狼抓兔子 (网络流-最大流)

版权声明:转载请标明出处 https://blog.csdn.net/weixin_41190227/article/details/89643724

题目描述

现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:

左上角点为(1,1),右下角点为(N,M)(上图中N=3,M=4).有以下三种类型的道路

1:(x,y)<==>(x+1,y)

2:(x,y)<==>(x,y+1)

3:(x,y)<==>(x+1,y+1)

道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下角(N,M)的窝中去,狼王开始伏击这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦。

输入输出格式

输入格式:

第一行为N,M.表示网格的大小,N,M均小于等于1000.

接下来分三部分

第一部分共N行,每行M-1个数,表示横向道路的权值.

第二部分共N-1行,每行M个数,表示纵向道路的权值.

第三部分共N-1行,每行M-1个数,表示斜向道路的权值.

输出格式:

输出一个整数,表示参与伏击的狼的最小数量.

输入输出样例

输入样例#1: 复制

3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6

输出样例#1: 复制

14

题目大意:读读题就理解了。

解题思路:把没一条边都用链式前向星构建出来,剩下的就是从左上第一个点跑最大流,到最后一个点位置。

题目链接:https://www.luogu.org/problemnew/show/P4001 

/*
@Author: Top_Spirit
@Language: C++
*/
//#include <bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std ;
typedef long long ll ;
typedef pair < ll, ll > P ;
const int Maxn = 1e6+ 10 ;
const int INF = 1 << 30 ;

int n, m, S, T ;
int head[Maxn << 3], cnt, s, t ;
int deep[Maxn << 3], que[Maxn << 3] ;

struct Node {
    int to, Next, w ;
}e[Maxn << 3] ;

void addEdge(int u, int v, int w){
    e[cnt].to = v ;
    e[cnt].w = w ;
    e[cnt].Next = head[u] ;
    head[u] = cnt++ ;
    e[cnt].to = u ;
    e[cnt].w = w ;
    e[cnt].Next = head[v] ;
    head[v] = cnt++ ;
}

bool bfs (){
    memset(deep, 0, sizeof(deep)) ;
    deep[S] = 1 ;
    que[1] = S ;
    int headd = 0, tail = 1 ;
    while (headd != tail){
        int v = que[++headd] ;
        for (int i = head[v]; i != -1; i = e[i].Next){
            if (e[i].w && !deep[e[i].to]){
                deep[e[i].to] = deep[v] + 1 ;
                que[++tail] = e[i].to ;
            }
        }
    }
    return deep[T] ;
}

int dfs (int now, int fl){
    if (now == T ) return fl ;
    int allfl = 0 ;
    for (int i = head[now]; i != -1 && fl; i = e[i].Next){
//        head[now] = i ;
        if (e[i].w && deep[e[i].to] == deep[now] + 1) {
            int x = dfs(e[i].to, min(fl, e[i].w)) ;
            e[i].w -= x ;
            e[i ^ 1].w += x ;
            fl -= x ;
            allfl += x ;
        }
    }
    if (!allfl) deep[now] = -2 ;
    return allfl ;
}

int dinic(){
    int ans = 0 ;
//    cout << bfs() << endl ;
    while (bfs()) {
//        cout << "+++++" << endl ;
//        cout << dfs (s, INF) ;
        ans += dfs(S, INF) ;
    }
    return ans ;
}

int main (){
    int x ;
    cin >> n >> m ;
    memset(head, -1, sizeof(head)) ;
    S = 0, T = n * m + 1 ;
    addEdge(S, 1, INF) ;
    for (int i = 0; i < n; i++){
        for (int j = 1; j < m; j++){
            cin >> x ;
            addEdge(m * i + j, m * i + j + 1, x) ;
        }
    }
    for (int i = 0; i < n - 1; i++){
        for (int j = 1; j <= m; j++){
            cin >> x ;
            addEdge(m * i + j, m * i + j + m, x) ;
        }
    }
    for (int i = 0; i < n - 1; i++){
        for (int j = 1; j < m; j++){
            cin >> x ;
            addEdge(m * i + j, m * i + j + m + 1, x) ;
        }
    }
    addEdge(n * m, T, INF) ;
    cout << dinic() << endl ;
    return 0 ;
}

猜你喜欢

转载自blog.csdn.net/weixin_41190227/article/details/89643724