写题之前读一下 推荐文章:《浅析最大最小定理在信息学竞赛中的应用》--周冬
1001: [BeiJing2006]狼抓兔子
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 25258 Solved: 6402
[ Submit][ Status][ Discuss]
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新加数据一组,可能会卡掉从前可以过的程序。
读了周冬的论文这题就很简单了。。转化为最短路求最小割。。
(bzoj不支持c++11,真的烦。。)
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <utility>
#include <queue>
using namespace std;
const int maxn = 2e6 + 100;
const int INF = 0x3f3f3f3f;
struct Node {
int u, v, w, next;
Node(int u, int v, int w, int next) : u(u), v(v) , w(w), next(next){};
Node(){};
}node[maxn * 3];
int head[maxn], total;
int dis[maxn];
bool visited[maxn];
void init() {
memset(head, -1, sizeof(head));
memset(visited, 0, sizeof(visited));
total = 0;
}
void add(int u, int v, int w) {
node[total] = Node(u, v, w, head[u]);
head[u] = total++;
node[total] = Node(v, u, w, head[v]);
head[v] = total++;
}
void spfa() {
memset(dis, INF, sizeof(dis));
queue<int> que;
visited[1] = 1;
dis[1] = 0;
que.push(1);
while (!que.empty()) {
int u = que.front();
que.pop();
for (int i = head[u]; i != -1; i = node[i].next) {
int v = node[i].v;
int w = node[i].w;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
if (!visited[v]) {
visited[v] = 1;
que.push(v);
}
}
}
visited[u] = 0;
}
}
int n, m;
int main() {
//freopen("in.txt", "r", stdin);
cin >> n >> m;
if (n == 1 || m == 1) {
n = max(n, m);
int ans = INF;
for (int i = 1; i < n; ++i) {
int a;
cin >> a;
ans = min(a, ans);
}
cout << ans << endl;
} else {
init();
int s = 1, t = n * m * 2;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j < m; ++j) {
int a;
cin >> a;
int d1 = i == n ? s : i * m + j;
int d2 = i == 1 ? t : (i - 1) * m + j + n * m;
//cout << d1 << " " <<d2 << " " << a << endl;
add(d1, d2, a);
}
}
for (int i = 1; i < n; ++i) {
for (int j = 1; j <= m; ++j) {
int a;
cin >> a;
int d1 = j == 1 ? s : i * m + (j - 1);
int d2 = j == m ? t : i * m + j + n * m;
//cout << d1 << " " <<d2 << " " << a << endl;
add(d1, d2, a);
}
}
for (int i = 1; i < n; ++i) {
for (int j = 1; j < m; ++j) {
int a;
cin >> a;
int d1 = i * m + j + n * m;
int d2 = i * m + j;
//cout << d1 << " " <<d2 << " " << a << endl;
add(d1, d2, a);
}
}
spfa();
cout << dis[t] << endl;
}
}