UVA1376.Animal Run (最小割转为最短路 && dijkstra)

Animal Run

Time Limit:6000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu

Submit Status

Description

Animals are living their painful lives in the zoo. Their activities are limited in a small area without any fun of snacks, alcohol, love or games. They are so upset that they decide to escape in a night.

As shown in Figure 1, the paths in the zoo can be expressed by a grid with nxm nodes. All the paths in the grid are two-way, horizontal or vertical or diagonal. Animals start from the upper left corner, and they are free if they can reach the lower right through paths.

Figure 1: This is a 3 x 4 nodes grid, the number beside the path indicating how many staff shall be sent to block this path

To protect public safety, the police are sent to block some paths to catch all the escaping animals. As it needs certain police staff to block a path, you are required to write a program for the police officer, and tell him how many staff at least shall be sent in order to defeat this Animal Escape.

Input

Input contains several cases, each describes one escape action.

Each case begins with two integers n and m, 3 nm 1000.

For the following n lines, there are m - 1 integers in each line, indicating how many staff shall be sent to block the horizontal paths respectively.

For the following n - 1 lines, there are m integers in each line, indicating how many staff shall be sent to block the vertical paths respectively.

For the following n - 1 lines, there are m - 1 integers in each line, indicating how many staff shall be sent to block the diagonal paths respectively.

Each line describes the paths from left to right. All integers in input file are no more than 1, 000, 000.

The last case is followed by a line containing two zeros. The size of the input data is about 16MB.

Output

For each case, output how many staff at least shall be sent to block all animals. Please output in the following format.

Sample Input

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
0 0

Sample Output

Case 1: Minimum = 14

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<queue>
  4 #include<algorithm>
  5 typedef long long ll ;
  6 const int M = 1000 + 5 ;
  7 const int maxn = 1005*1005*3   ;
  8 int hori[M][M] , vert[M][M] , diag[M][M] ;
  9 int st , ed ;
 10 const int inf = 0x3f3f3f3f ;
 11 struct edge
 12 {
 13     int u , v , w ;
 14 };
 15
 16 struct heapnode
 17 {
 18     ll d , u ;
 19     bool operator < (const heapnode & rhs ) const
 20     {
 21         return d > rhs.d ;
 22     }
 23 };
 24
 25 int n , m ;
 26 std::vector <edge> edges ;
 27 std::vector <int> g[maxn] ;
 28 bool done[maxn] ;
 29 ll d[maxn] ;
 30 int p[maxn] ;
 31
 32 void init (int n)
 33 {
 34     for (int i = 0 ; i <= n ; i ++ ) g[i].clear ();
 35     edges.clear () ;
 36 }
 37
 38 void addedge (int u , int v , int w)
 39 {
 40     edges.push_back ( (edge) {u , v , w}) ;
 41     int m = edges.size () ;
 42     g[u].push_back (m - 1) ;
 43 }
 44
 45 void dijkstra (int s)
 46 {
 47     std::priority_queue <heapnode> q ;
 48     for (int i = 0 ; i <= ed ; i ++) d[i] = inf ;
 49     d[s] = 0 ;
 50     memset (done , 0 , sizeof(done))  ;
 51     q.push ( (heapnode) {0 , s}) ;
 52     while ( !q.empty ()) {
 53         heapnode x = q.top () ; q.pop () ;
 54         int u = x.u ;
 55         if (done[u]) continue ;
 56         done[u] = true ;
 57         for (int i = 0 ; i < g[u].size () ; i ++) {
 58             edge e = edges[g[u][i]] ;
 59            // printf ("%d > %d + %d\n" , d[e.v] , d[u] , e.w ) ;
 60             if ( d[e.v] > d[u] + e.w ) {
 61                 d[e.v] = d[u] + 1ll * e.w ;
 62                 p[e.v] = g[u][i] ;
 63                 q.push ( (heapnode) {d[e.v] , e.v }) ;
 64             }
 65         }
 66     }
 67 }
 68
 69 void build ()
 70 {
 71     for (int i = 0 ; i < n - 1 ; i ++) {
 72         for (int j = 0 ; j < m - 1 ; j ++) {
 73             int u = i * 2 * (m - 1) + 2 * j , v = i * 2 * (m - 1) + 2 * j + 1 ;
 74             addedge (u , v , diag[i][j]) ;
 75             addedge(v , u , diag[i][j]) ;
 76           //  printf ("m=%d\n" , m ) ;
 77         }
 78     }
 79     for (int i = 1 ; i < n - 1; i ++) {
 80         for (int j = 0 ; j < m - 1 ; j ++) {
 81             int u = (i - 1) * 2 * (m - 1)+ 2 * j , v = i * 2 * (m - 1)+ 2 * j + 1 ;
 82             addedge (u , v , hori[i][j]) ;
 83             addedge (v , u , hori[i][j]) ;
 84         }
 85     }
 86     for (int j = 0 ; j < m - 1 ; j ++) {
 87         addedge (2 * j + 1 , st , hori[0][j]) ;
 88         addedge (ed , (n - 2 ) * 2 * (m - 1) + 2 * j , hori[n - 1][j]) ;
 89     }
 90     for (int i = 0 ; i < n - 1 ; i ++) {
 91         for (int j = 1 ; j < m - 1 ; j ++) {
 92             int u = i * 2 * (m - 1) + 2 * j - 1, v = i * 2 * (m - 1 ) + 2 * j  ;
 93             addedge (u , v , vert[i][j]) ;
 94             addedge (v , u , vert[i][j]) ;
 95         }
 96     }
 97     for (int i = 0 ; i < n - 1 ; i ++) {
 98         addedge (ed , i * 2 * (m - 1 ), vert[i][0] ) ;
 99         addedge ((i + 1) * 2 * (m - 1) - 1 , st , vert[i][m - 1]) ;
100     }
101    // for (int i = 0 ; i < edges.size () ; i ++) printf ("%d--->%d(%d)\n" , edges[i].u , edges[i].v , edges[i].w ) ;
102 }
103
104 int main ()
105 {
106    // freopen ("a.txt" , "r" , stdin ) ;
107    int cas = 1 ;
108     while (~ scanf ("%d%d" , &n , &m ) ) {
109         if (n == 0 && m == 0) break ;
110         st = (n - 1) * 2 * (m - 1)  ; ed = (n - 1) * 2 * (m - 1) + 1 ;//源点 , 汇点
111         int rhs = std::max (n , m ) ;
112         init (3 * rhs * rhs ) ;
113         for (int i = 0 ; i < n; i ++) for (int j = 0 ; j < m - 1 ; j ++) scanf ("%d" , &hori[i][j]) ;
114         for (int i = 0 ; i < n - 1 ; i ++) for (int j = 0 ; j < m ; j ++) scanf ("%d" , &vert[i][j]) ;
115         for (int i = 0 ; i < n - 1 ; i ++) for (int j = 0 ; j < m - 1 ; j ++) scanf ("%d" , &diag[i][j]) ;
116         build () ;
117         dijkstra (ed) ;
118       //  for (int i = 0 ; i <= ed ; i ++) printf ("%2d ", i) ; puts ("") ;
119       //  for (int i = 0 ; i <= ed ; i ++) printf ("%2d " , d[i]) ; puts ("") ;
120         printf ("Case %d: Minimum = %lld\n" , cas ++ , d[st]) ;
121     }
122     return 0 ;
123 }

建图真心好难,一开始一直在yy怎么设点:比如说一个个命名 ,先把数据存图 , 再在图上搜相邻点间的关系。。。但结果感觉都非常奇怪。

后来想到了一个出路,就是他给的数据存到hori[][] , vert[][] , diag[][] .

然后用i , j来表示一个个三角形的下标。并分别将以上三种边相邻的三角形建立关系。

然后套套dijkstra模板过了。

时间: 2024-12-16 04:05:37

UVA1376.Animal Run (最小割转为最短路 && dijkstra)的相关文章

[bzoj1001][BeiJing2006]狼抓兔子-题解[平面图最小割转最短路]/[Dinic求最小割]

Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路

UVALive - 3661 Animal Run (平面图+最小割+对偶图+最短路)

题目大意:有很多只小动物要从左上角跑到右下角,给出每条线路所需的人手,问至少需要多少人手,才能将所有动物抓住 解题思路:最小割,就是最小割,但是用最大流处理不了,边太多了 具体可以参考算法合集之<浅析最大最小定理在信息学竞赛中的应用> 知道了这个后,这题估计就可以解了 给出我的建图方式 将每一个小三角形从左往右,从上到下依次编号为1-2-3.. 每行的同一个三角行的编号差就是2 * (m - 1) 如图 #include <cstdio> #include <cstring&

hdu 3870(平面图最小割转最短路)

Catch the Theves Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65768/32768 K (Java/Others)Total Submission(s): 1640    Accepted Submission(s): 514 Problem Description A group of thieves is approaching a museum in the country of zjsxzy,now t

【bzoj2007】[Noi2010]海拔 最小割+对偶图+最短路

题目描述 YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域.简单起见,可以将YT市看作一个正方形,每一个区域也可看作一个正方形.从而,YT城市中包括(n+1)×(n+1)个交叉路口和2n×(n+1)条双向道路(简称道路),每条双向道路连接主干道上两个相邻的交叉路口.下图为一张YT市的地图(n = 2),城市被划分为2×2个区域,包括3×3个交叉路口和12条双向道路. 小Z作为该市的市长,他根据统计信息得到了每天上班高峰期间YT市每条道路两个方向的人流量,即在高峰期间沿着

【Algorithm】平面图最小割转最短路

杭电上碰巧有几道求最小割的题目,用网络流解超时.通过离散数学中的一些知识可以将平面图最小割转化为最短路径,通过最短路解提高效率.这个转化过程很简单,但是很巧妙,详细内容可以参考<浅析最大最小定理在信息学竞赛中的应用>. 1. [HDU] 3870 Catch the Theves有一个网格拓扑,每条边都表示有$A_{ij}$个小偷,现在希望对其中一条边部署警察,使得小偷不可能偷到右下角的财宝.求至少需要多少个警察?这题是个挺有实际意义的题目,基本思路也很简单.因为题目给定小偷都从左上角出发向右

【BZOJ2007】【Noi2010】海拔 平面图最小割转最短路

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43280891"); } 题解:这个模型很水,不需要极角序神马转对偶图,直接乱搞就行. 然后目的是把图割开,那么只需要跑S->T最短路就行. 要做平面图转对偶图不妨去这篇. [BZOJ2965]保护古迹 平面图转对偶图,暴力,网络流 还有就是某人

HDU3870 Catch the Theves(平面图最小割转最短路)

题目大概说给一个n×n的方格,边有权值,问从求(1,1)到(n,n)的最小割. 点达到了160000个,直接最大流不好.这题的图是平面图,求最小割可以转化成求其对偶图的最短路,来更高效地求解: 首先源点汇点间新加一条边,然后构造其对偶图: 面作为对偶图的点:而源点到汇点之间新加的边划分出来的两个面分别作为对偶图的源点和汇点 如果两个面之间有边则两个面在对偶图对应的点连边,权值为原来的边权:去掉对偶图源点和汇点之间边 这样可以发现,对偶图的源点到汇点的一条路径就对应这原图的源点到汇点的一个割边集,

bzoj 2007 [Noi2010]海拔——最小割转最短路

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2007 一个点的高度一定不是0就是1.答案一定形如一个左上角的连通块全是0的点.一个右下角的连通块全是1的点. 注意从东到西还有从南到北的边也有用!因为不一定是一个阶梯形的,还可以拐来拐去,只是一定是两个连通块罢了. 所以最小割一下那个分界线就行了.但会TLE. #include<cstdio> #include<cstring> #include<algorithm&g

BZOJ1001: [BeiJing2006]狼抓兔子 (最小割转最短路)

浅析最大最小定理在信息学竞赛中的应用---周东 ↑方法介绍 对于一个联通的平面图G(满足欧拉公式) 在s和t间新连一条边e; 然后建立一个原图的对偶图G*,G*中每一个点对应原图中每一个面,每一条边对应分割面的每一条边; 那么对偶图G*中,以原图s和t间边e新划分出的面作为起点(s*),最外的面作为终点(t*); 那么从s*到t*的每一条路都是原图G的一个割; 下图来自上方标出百度文库网址的ppt; 然后用堆(优先队列)优化的迪杰斯特拉,复杂度 O((m+n)logn) n为点数,m为边数...