版权声明:转载请标明出处 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
题目大意:读读题就理解了。
解题思路:把没一条边都用链式前向星构建出来,剩下的就是从左上第一个点跑最大流,到最后一个点位置。
/* @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 ; }