bzoj1001狼抓兔子——網路流平面圖問題
1001: [BeiJing2006]狼抓兔子
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 25715 Solved: 6529
[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
Output
輸出一個整數,表示參與伏擊的狼的最小數量.
Sample Input
3 45 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
14HINT
2015.4.16新加資料一組,可能會卡掉從前可以過的程式。
Source
HOME
其實就是一道模板題……然而建成了單向邊……用的是isap,雙向邊只需要在建邊的時候把反向邊建成cap就好了
inline void add_edge(int x, int y, int cap) {
e[p] = Edge(y, h[x], cap, 0); h[x] = p++;
e[p] = Edge(x, h[y], cap, 0); h[y] = p++;
}
然後……沒有然後
#include <bits/stdc++.h> using namespace std; const int MAXN = 1000003; const int MAXE = 6000003; const int INF = 0x3f3f3f3f; struct Edge{ int to, nxt, cap, flow; Edge() {} Edge(int to, int nxt, int cap, int flow):to(to), nxt(nxt), cap(cap), flow(flow) {} }e[MAXE]; int n, m; int h[MAXN], p; int source, sink, tot; int pre[MAXN], num[MAXN], cur[MAXN]; int d[MAXN]; bool vis[MAXN]; queue<int> q; inline void add_edge(int x, int y, int cap) { e[p] = Edge(y, h[x], cap, 0); h[x] = p++; e[p] = Edge(x, h[y], cap, 0); h[y] = p++; } void bfs() { memset(vis, 0, sizeof(vis)); q.push(sink); vis[sink] = 1; d[sink] = 0; while(!q.empty()) { int u = q.front(); q.pop(); num[d[u]]++; for(int i = h[u]; ~i; i = e[i].nxt) { int v = e[i].to; if(!vis[v]) { vis[v] = 1; d[v] = d[u] + 1; q.push(v); } } } } void augment(int flow) { for(int i = source; i != sink; i = e[cur[i]].to) { e[cur[i]].flow += flow; e[cur[i] ^ 1].flow -= flow; } } int isap() { memset(num, 0, sizeof(num)); bfs(); memcpy(cur, h, sizeof(h)); int u = source, flow = 0, f = INF; while(d[source] < tot) { bool fg = 0; for(int i = cur[u]; ~i; i = e[i].nxt) { if(e[i].cap > e[i].flow && d[u] == d[e[i].to] + 1) { pre[e[i].to] = u; cur[u] = i; u = e[i].to; f = min(f, e[i].cap - e[i].flow); fg = 1; if(u == sink) { flow += f; augment(f); f = INF; u = source; } break; } } if(fg) continue; if(--num[d[u]] == 0) break; int M = tot - 1; for(int i = h[u]; ~i; i = e[i].nxt) { if(e[i].cap > e[i].flow && M > d[e[i].to]) { M = d[e[i].to]; cur[u] = i; } } num[d[u] = M + 1]++; if(u != source) u = pre[u]; } return flow; } signed main() { scanf("%d%d",&n,&m); int x; source = 1; sink = n * m; tot = sink; memset(h, -1, sizeof(h)); for(int i = 1; i <= n; i++) for(int j = 1; j < m; j++) { scanf("%d",&x); add_edge(m * (i - 1) + j, m * (i - 1) + j + 1, x); } for(int i = 1; i < n; i++) for(int j = 1; j <= m; j++) { scanf("%d",&x); add_edge(m * (i - 1) + j, m * (i) + j, x); } for(int i = 1; i < n; i++) for(int j = 1; j < m; j++) { scanf("%d",&x); add_edge(m * (i - 1) + j, m * (i) + j + 1, x); } printf("%d\n", isap()); }
相關推薦
bzoj1001狼抓兔子——網路流平面圖問題
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 25715 Solved: 6529 [Submit][Status][Discuss] Description 現在小朋
bzoj1001 狼抓兔子 網路流(水)
這道題正解不是網路流,但是網路流(最小割)在這種圖上跑得飛起,就能水(2016.8.12)。直接貼程式碼。 #include<iostream> #include<cstdio> #include<queue> usin
BZOJ1001狼抓兔子(網路流最小割)
BZOJ1001 狼抓兔子 題目描述 現在小朋友們最喜歡的”喜羊羊與灰太狼”,話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形: 左上角點為(1,1),右下角點為(N,M
[日常摸魚]bzoj1001狼抓兔子-最大流最小割
百萬 reg ret 最短 fin 網絡圖 通過 聯通 gpo 題意就是求最小割… 然後我們有這麽一個定理(最大流-最小割定理 ): 任何一個網絡圖的最小割中邊的容量之和等於圖的最大流。 (下面直接簡稱為最大流和最小割) 證明: 如果最大流>最小割,那把這些割邊刪去之
BZOJ1001:狼抓兔子(最小割最大流+vector模板)
cout 地形 ++ 能夠 can 圖片 jpg http img 1001: [BeiJing2006]狼抓兔子 Description 現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的,而且現在的兔子還比較笨,它們只有兩個窩,現在
BZOJ1001狼抓兔子(平面圖最小割)
題目大意:給一個n*m的網格圖,表示一個地圖。起點(1,1),終點(n,m)。每條邊上有一個權值,表示該路徑上的兔流量。現在一些兔子從起點沿著邊跑到終點。然後有一些大灰狼要抓這些兔子。一隻狼能抓一隻兔子。現在狼王想知道至少要派多少狼能堵住兔子的路。 題目分析:很裸的最小割
bzoj1001狼抓兔子
n) std 灰太狼 top bool 表示 continue 能夠 long 1001: [BeiJing2006]狼抓兔子 現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對
【dinic模板】BZOJ1001 狼抓兔子
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace st
BZOJ1001 狼抓兔子
最小割 程式碼 # include <bits/stdc++.h> # define IL inline # define RG register # define Fill(a, b) memset(a, b, sizeof(a)) # def
狼抓兔子 HYSBZ - 1001(網路流/平面圖轉對偶圖求最短路)
傳送門 題意:有個方格,求從(1,1)到(n,m)的最小割 題解:有兩種方法,第一種:使用dinic演算法,但是需要有個優化就是當每次增廣時,如果一旦哪條路增廣失敗,那麼就把這條路直接賦值為-1,把它堵死,這樣優化可以達到很高。 附上第一種程式碼:(使用白書上的dinic演算法呢,可以過
BZOJ1001[BeiJing2006]狼抓兔子最小割網路流
Description 現在小朋友們最喜歡的”喜羊羊與灰太狼”,話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形: 左上角點為(1,1),右下角點為(N,M)(上圖中N=
BZOJ1001 [BeiJing2006]狼抓兔子(網路流最小割)
題目可以轉化為:從原圖中選出一個邊集,使得去掉它之後,(1,1)與(n,m)不通 即:以(1,1)為源,(n,m)為匯,求該圖最小割 不過由於節點過多,直接對輸入的圖求最小割的話會超時 轉化:求
bzoj1001 [BeiJing2006]狼抓兔子(網路流dinic演算法||最短路spfa)
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MB Submit: 24017 Solved: 6
[BZOJ1001][BeiJing2006]狼抓兔子 && 平面網路流
傳說這個題可以轉最短路 於是我去轉最短路 於是搞的我無比糾結 連邊麻煩的要死 #include<cstdio> #include<algorithm> #include<cstring> #include<iostream>
平面圖轉對偶圖(Bzoj1001:狼抓兔子)
fin con names esp || ons down ace ++ 如果只會用最小割做這道題那就太菜辣 引入 來自某學長 平面圖:在平面上邊不相交的圖(邊可以繞著畫) 那麽平面圖的邊與邊就圍成了許多個區域(這與你畫圖的方式有關) 定義對偶圖:把相鄰的兩個區域連上邊,形
BZOJ1001 [BeiJing2006]狼抓兔子 平面圖轉對偶圖,最小割轉最短路
bits ges code inf 如果 對偶圖 += ron oid 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 28885 Solved: 7540[Submit
1001: [BeiJing2006]狼抓兔子[dinic網路流]
現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形: 左上角點為(1,1),右下角點為(N,M)(上圖中N=4,M=5).有以下三種類型的道路 1:(x,y)<
[BJOI2006]狼抓兔子——最小割轉對偶圖最短路 [無效]網路流之轉換對偶圖
其實這個題直接Dinic跑最小割可過。 (小優化是: 無向圖建網路流,一條邊不用建成4條,可以正反容量都是邊權即可。完全等價 ) [無效]網路流之轉換對偶圖 一個巧妙的事情是,如果建邊合適的話,最小割就是右上部分到左下部分的最短路。 看圖就明白了。 注意一個正方形
【BZOJ1001】【Beijing2006】狼抓兔子(平面圖轉對偶圖:最小割+最短路)
題目描述 傳送門 題解 題目描述很明顯這就是一道最小割,不過跑最大流的話會TLE。 我們發現這是一個平面圖(什麼是平面圖?),那麼我們就可以參考平面圖轉對偶圖的思想,將這道題轉化成最短路。
bzoj1001: [BeiJing2006]狼抓兔子(最大流)
題目傳送門 解法: 每一隻兔子就需要一隻狼。 那麼我們只需要求出最多能通過多少隻兔子即可。 然後就派多少隻狼就行了唄。。 因為兔子從哪裡過來的我就在哪裡放狼。 所以狼的數量一定等於最多兔子通過的數量 題目並不要求求方案,所以不需知道兔子從哪過來。