UVA1376.Animal Run (最小割转为最短路 && dijkstra)
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.
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 n, m 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
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模板过了。