bzoj1001:[BeiJing2006]狼抓兔子
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)
道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,
开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击
这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.
Input
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
输入文件保证不超过10M
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
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
14
HINT
2015.4.16新加数据一组,可能会卡掉从前可以过的程序。
Source
题解:
考虑平面图最小割转对偶图最短路,这两个转换完就是完全一样的东西,包括数量,然后你就可以写什么最小割计数了,但是这题只要求最短路。
那你跑一遍spfa就好了。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <iostream>
int n, m, s, t;
struct edge { int to, val; edge *next; } e[8000010], *et = e, *last[1000010];
void add(int u, int v, int w) {
//printf("edge : %d -> %d : %d\n", u, v, w);
*++et = (edge) {v, w, last[u]}, last[u] = et;
*++et = (edge) {u, w, last[v]}, last[v] = et;
}
int vis[2000010], dis[2000010];
int main() {
scanf("%d%d", &n, &m);
s = (n-1)*(m-1)*2+1, t = s+1;
for(int i = 1; i <= n; i++)
for(int j = 1; j < m; j++) {
int v;
scanf("%d", &v);
if(i == 1) add(s, (i-1)*(m-1)*2+j*2, v);
else if(i == n) add((i-2)*(m-1)*2+j*2-1, t, v);
else add((i-2)*(m-1)*2+j*2-1, (i-1)*(m-1)*2+j*2, v);
}
for(int i = 1; i < n; i++)
for(int j = 1; j <= m; j++) {
int v;
scanf("%d", &v);
if(j == 1) add((i-1)*(m-1)*2+j*2-1, t, v);
else if(j == m) add(s, (i-1)*(m-1)*2+j*2-2, v);
else add((i-1)*(m-1)*2+j*2-2, (i-1)*(m-1)*2+j*2-1, v);
}
for(int i = 1; i < n; i++)
for(int j = 1; j < m; j++) {
int v;
scanf("%d", &v);
add((i-1)*(m-1)*2+j*2-1, (i-1)*(m-1)*2+j*2, v);
}
static int q[2000010]; int l = 0, r = 0;
memset(dis, 63, sizeof dis);
vis[q[r++] = s] = 1; dis[s] = 0;
while(l < r) {
int u = q[l++]; if(l >= n*m*2) l -= n*m*2;
for(edge *it = last[u]; it; it = it->next)
if(dis[u]+(it->val) < dis[it->to]) {
dis[it->to] = dis[u]+(it->val);
if(!vis[it->to]) {
vis[it->to] = 1, q[r++] = it->to;
if(r >= n*m*2) r -= n*m*2;
}
}
vis[u] = 0;
}
printf("%d\n", dis[t]);
}

浙公网安备 33010602011771号