【平面图最小割】BZOJ1001- [BeiJing2006]狼抓兔子

【题目大意】
左上角点为(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只狼伏击,求封锁道路的最小狼数。

【思路】
显然这是最小割,但是最小割效率太低。可以发现这是一张平面图,根据平面图的性质,平面图最小割=对偶图的最短路。所谓对偶图,简单理解就是把面转为点,然后将面之间的边作为连接两个点的边。本题中建立的对偶图如下:

显然可以发现,最短路必然是最小割。

【错误点】
注意一下面转点后,对偶图点的数量和原来点的数量不一样,大概为2倍,数组要开足够大,否则RE!

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 #include <utility>
 8 #define S 0
 9 #define T 2*(m-1)*(n-1)+1
10 using namespace std;
11 const int MAXN=2000000;
12 const int INF=0x7fffffff;
13 struct edge
14 {
15     int fr,to,len;
16 };
17 int n,m,w;
18 vector<edge> E[MAXN];
19
20 void addedge(int u,int v,int w)
21 {
22     //cout<<"!"<<u<<‘ ‘<<v<<‘ ‘<<w<<endl;
23     E[u].push_back((edge){u,v,w});
24     E[v].push_back((edge){v,u,w});
25 }
26
27 int dijkstra()
28 {
29     priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > que;
30     int dis[MAXN],vis[MAXN];
31     memset(vis,0,sizeof(vis));
32     for (int i=S+1;i<=T;i++) dis[i]=INF;
33     dis[S]=0;
34     que.push(make_pair<int,int>(0,S));
35     while (!que.empty())
36     {
37         int head=que.top().second;que.pop();
38         if (!vis[head])
39         {
40             vis[head]=1;
41             for (int i=0;i<E[head].size();i++)
42             {
43                 edge Edge=E[head][i];
44                 if (!vis[Edge.to] && dis[Edge.to]>dis[Edge.fr]+Edge.len)
45                 {
46                     dis[Edge.to]=dis[Edge.fr]+Edge.len;
47                     que.push(make_pair<int,int>(dis[Edge.to],Edge.to));
48                 }
49             }
50         }
51     }
52     return (dis[T]);
53 }
54
55 void init()
56 {
57     for (int i=0;i<n;i++)
58         for (int j=0;j<m-1;j++)
59         {
60             scanf("%d",&w);
61             if (i==0) addedge(2*(j+1),T,w);
62                 else if (i==n-1) addedge(S,(n-2)*(m-1)*2+2*j+1,w);
63                     else addedge((i-1)*(m-1)*2+2*j+1,i*(m-1)*2+2*j+2,w);
64         }
65     for (int i=0;i<n-1;i++)
66         for (int j=0;j<m;j++)
67         {
68             scanf("%d",&w);
69             if (j==0) addedge(S,i*2*(m-1)+1,w);
70                 else if (j==m-1) addedge((i+1)*2*(m-1),T,w);
71                     else addedge(i*2*(m-1)+j*2,i*2*(m-1)+2*j+1,w);
72         }
73     for (int i=0;i<(n-1);i++)
74         for (int j=0;j<(m-1);j++)
75         {
76             scanf("%d",&w);
77             //cout<<i<<‘ ‘<<j<<‘ ‘;
78             addedge(i*2*(m-1)+2*j+1,i*2*(m-1)+2*j+2,w);
79         }
80 }
81
82 int main()
83 {
84     scanf("%d%d",&n,&m);
85     if (n==1 && m==1) cout<<0<<endl;
86         else
87         {
88             init();
89             cout<<dijkstra()<<endl;
90         }
91     return 0;
92 }
时间: 2024-10-27 09:42:43

【平面图最小割】BZOJ1001- [BeiJing2006]狼抓兔子的相关文章

bzoj1001 [BeiJing2006]狼抓兔子

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

BZOJ1001: [BeiJing2006]狼抓兔子【最短路】

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1001 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 27684  Solved: 7127 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的

[bzoj1001][BeiJing2006]狼抓兔子-题解[平面图最小割转最短路]/[Dinic求最小割]

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

BZOJ1001[BeiJing2006]狼抓兔子(无向图最小割)

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 这题的题意其实就是求一个最小割,但是由于是无向图,所以加边的时候,两边的流量都要是输入的权值,然后就是一个dinic求一下最小割. 但是这题貌似有很高超的技巧来搞,可以把平面图上的最小割转成对偶图上的最短路来做,这样可以起到很明显的优化效果.现在还不是很明白,如果以后明白了,会再来更新. dinic: #include <cstdio> #include <cstring&g

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

【平面图】【最小割】【最短路】【Heap-Dijkstra】bzoj1001 [BeiJing2006]狼抓兔子

http://wenku.baidu.com/view/8f1fde586edb6f1aff001f7d.html #include<cstdio> #include<queue> #include<cstring> using namespace std; typedef long long ll; #define N 1001 int n,m,S,T,nn; struct Point{int u,d;}; bool operator < (Point a,Po

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

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

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_2001_[BeiJing2006]狼抓兔子_最小割转对偶图

BZOJ_2001_[BeiJing2006]狼抓兔子 题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 分析:思路同NOI2010海拔. 注意无向图. 代码: 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <queue> 5 using namespace std; 6 #define S