BZOJ 1001:[BeiJing2006]狼抓兔子(最小割)

http://www.lydsy.com/JudgeOnline/problem.php?id=1001

题意:中文。

思路:很明显是最小割,转化为最大流做。一开始看那么多点,但还是试了一下,居然过了。迷。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <queue>
 6 using namespace std;
 7 #define N 1000010
 8 #define INF 0x3f3f3f3f
 9 struct Edge {
10     int v, cap, nxt;
11 } edge[N*6];
12 int head[N], cur[N], pre[N], tot, gap[N], dis[N], S, T;
13
14 void Add(int u, int v, int cap) {
15     edge[tot] = (Edge) {v, cap, head[u]}; head[u] = tot++;
16     edge[tot] = (Edge) {u, cap, head[v]}; head[v] = tot++;
17 }
18
19 int BFS() {
20     memset(gap, 0, sizeof(gap));
21     memset(dis, INF, sizeof(dis));
22     queue<int> que;
23     que.push(T);
24     dis[T] = 0; gap[0] = 1;
25     while(!que.empty()) {
26         int u = que.front(); que.pop();
27         for(int i = head[u]; ~i; i = edge[i].nxt) {
28             int v = edge[i].v;
29             if(INF != dis[v]) continue;
30             dis[v] = dis[u] + 1;
31             gap[dis[v]]++;
32             que.push(v);
33         }
34     }
35 }
36
37 int ISAP(int n) {
38     BFS();
39     memcpy(cur, head, sizeof(cur));
40     int flow, ans = 0, u = pre[S] = S, i, index;
41     while(dis[S] < n) {
42         if(u == T) {
43             flow = INF;
44             for(i = S; i != T; i = edge[cur[i]].v)
45                 if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
46             for(i = S; i != T; i = edge[cur[i]].v)
47                 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow;
48             ans += flow; u = index;
49         }
50         for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap > 0 && dis[edge[i].v] == dis[u] - 1) break;
51         if(~i) {
52             cur[u] = i; pre[edge[i].v] = u; u = edge[i].v;
53         } else {
54             if(--gap[dis[u]] == 0) break;
55             int md = n + 1;
56             for(i = head[u]; ~i; i = edge[i].nxt)
57                 if(edge[i].cap > 0 && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;
58             gap[dis[u] = md + 1]++;
59             u = pre[u];
60         }
61     }
62     return ans;
63 }
64
65 int main() {
66     int n, m, w;
67     scanf("%d%d", &n, &m);
68     memset(head, -1, sizeof(head));
69     tot = 0;
70     for(int i = 0; i < n; i++)
71         for(int j = 2; j <= m; j++)
72             scanf("%d", &w), Add(j - 1 + i * m, j + i * m, w);
73     for(int i = 1; i < n; i++)
74         for(int j = 1; j <= m; j++)
75             scanf("%d", &w), Add(j + (i - 1) * m, j + i * m, w);
76     for(int i = 1; i < n; i++)
77         for(int j = 2; j <= m; j++)
78             scanf("%d", &w), Add(j - 1 + (i - 1) * m, j + i * m, w);
79     S = 1, T = n * m;
80     printf("%d\n", ISAP(T + 1));
81     return 0;
82 }
时间: 2024-10-06 02:21:17

BZOJ 1001:[BeiJing2006]狼抓兔子(最小割)的相关文章

BZOJ 1001: [BeiJing2006]狼抓兔子 最小割

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)

bzoj 1001 [BeiJing2006]狼抓兔子 最小割+最短路

题面 题目传送门 解法 将最大流转化成最小割,然后跑最短路即可 具体如何见图可以参考下图 尽量用dijkstra 代码 #include <bits/stdc++.h> #define PI pair <int, int> #define mp make_pair #define N 1010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x

BZOJ 1001: [BeiJing2006]狼抓兔子【最大流/SPFA+最小割,多解】

1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 23822  Solved: 6012[Submit][Status][Discuss] Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M

BZOJ 1001: [BeiJing2006]狼抓兔子 对偶图

本题是最大流转最小割转对偶图最短路 推荐周东的<浅析最大最小定理在信息学竞赛中的应用> 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MB Submit: 12166  Solved: 2866 [Submit][Status][Discuss] Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在

BZOJ 1001: [BeiJing2006]狼抓兔子(最短路)

平面图的最小割转化为对偶图的最短路(资料:两极相通——浅析最大最小定理在信息学竞赛中的应用) ,然后DIJKSTRA就OK了. ------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<que

BZOJ 1001 [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) 道路上的权值表示这条路上最多能够通过的兔子数,道路是

BZOJ 1001 [BeiJing2006]狼抓兔子

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 题意: ... 很容易想到求的是一个最小割=最大流. 之前一直用的刘汝佳的模板STL过题,很久没用过数组模拟了. 再次熟悉一下写法,first数组是索引数组,标记的结点的最后一条边,利用next数组找到上一条边. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define N 1100000 6 int n,m,

bzoj 1001: [BeiJing2006]狼抓兔子 最短路+对偶图

题意:求一个表格图的最小割. 分析:这题如果套上一个网络流的话是会挂的,所以我们要把该图转换成它的对偶图,具体方法可以参照两级相通----浅析最大最小定理在信息学竞赛中的应用 By 周冬.然后跑对短路就好了. 良心的出题人居然没卡spfa 这题要特判n=1 or m=1的情况 这次一开始无限12msWA的原因是spfa的结束条件是until head>=tail,而我用的是循环队列--不想多说,以后一定要注意才行啊. 代码: const maxn=2000009; var s,t,n,m,e:l

bzoj 1001: [BeiJing2006]狼抓兔子 平面图最小割

平面图跑最大流 可以转换为其对偶图跑最短路 一个环对应一个割  找到最小环(即最短路)极为所求,注意辅助边的建立 加入读入优化  不过时间还是一般  估计是dij写的不好   大神勿喷~~~ /************************************************************** Problem: 1001 User: 96655 Language: C++ Result: Accepted Time:1724 ms Memory:95120 kb ****

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

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