题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1001
1001: [BeiJing2006]狼抓兔子
Time Limit: 15 Sec Memory Limit: 162 MB
Submit: 27684 Solved: 7127
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
题外话:看着这图想到对偶图,然后就想起了bzoj2007海拔那题......
题解:题意就是求最小割,把平面图转化成对偶图然后从右上角到左下角跑dijkstra就可以了......注意双向边,数组开大点。
(一开始用vector写结果爆内存了,还是数组好用...)
#include<bits/stdc++.h>
#define CLR(a, b) memset((a), (b), sizeof((a)))
using namespace std;
const int INF = 1e9+;
const int N = 2e6+;
const int M = *N;
int head[N];
int d[N], vis[N];
struct Edge{
int v, c, nex;
}E[M];
int num = ;
void add(int u,int v,int c){
E[num].v = v; E[num].c = c; E[num].nex = head[u];
head[u] = num++;
}
struct qnode{
int v,c,x;
qnode(int _v=,int _c=,int _x=):v(_v),c(_c),x(_x){}
bool operator < (const qnode &r)const{
return r.c<c;
}
};
void dij(int s, int n) {//起点、终点
CLR(vis, );
for(int i = ; i <= n; i++) d[i] = INF;
priority_queue<qnode>q;
while(!q.empty()) q.pop();
d[s] = ;
q.push(qnode(s, ));
qnode t;
while(!q.empty()) {
t = q.top(); q.pop();
int u = t.v;
if(vis[u])continue;
vis[u] = true;
for(int i = head[u]; ~i; i = E[i].nex) {
int v = E[i].v;
int c = E[i].c;
if(!vis[v] && d[v] > d[u] + c) {
d[v] = d[u] + c;
q.push(qnode(v, d[v]));
}
}
}
}
int main() {
int n, m;
int k, i, j, u, v, w;
CLR(head,-); CLR(E, ); scanf("%d%d", &n, &m);
int s = ; //起点
int t = *(n-)*(m-)+;//终点 for(i = ; i <= n; ++i) {
for(j = ; j < m; ++j) {
scanf("%d", &w);
u = ( i==? s : (*(i-)-)*(m-)+j );
v = ( i==n? t : *(i-)*(m-)+j );
add(u, v, w); add(v, u, w);
}
}
for(i = ; i < n; ++i) {
for(j = ; j <= m; ++j) {
scanf("%d", &w);
u = ( j==m? s : *(i-)*(m-)+j-+m );
v = ( j==? t : *(i-)*(m-)+j- );
add(u, v, w); add(v, u, w);
}
}
for(i = ; i < n; ++i) {
for(j = ; j < m; ++j) {
scanf("%d", &w);
u = *(i-)*(m-)+j;
v = (*(i-)+)*(m-)+j;
add(u, v, w); add(v, u, w);
}
} dij(s, t);
printf("%d\n", d[t]);
return ;
}
2640ms