1. 程式人生 > >【BZOJ1001】【BJOI2006】狼抓兔子(對偶圖,最短路)

【BZOJ1001】【BJOI2006】狼抓兔子(對偶圖,最短路)

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只狼,
才能完全封鎖這條道路,你需要幫助狼王安排一個伏擊方案,使得在將兔子一網打盡的前提下,參與的
狼的數量要最小。因為狼還要去找喜羊羊麻煩.

Solution

顯然是個最小割問題。
開始寫了個sap,發現TLE了,網上的程式碼好像都是Dinic而且都加了點玄學優化才過的。
其實可以用對偶圖解決,一個圖的最大流等於最小割等於其對應對偶圖的最短路。

Source

/************************************************
 * Au: Hany01
 * Date: Apr 4th, 2018
 * Prob: [BZOJ1001][BJOI2006] 狼抓兔子
 * Email: [email protected]
************************************************/
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int, int> PII; #define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout) #define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i) #define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i) #define Set(a, b) memset(a, b, sizeof(a)) #define Cpy(a, b) memcpy(a, b, sizeof(a)) #define x first #define y second #define pb(a) push_back(a) #define mp(a, b) make_pair(a, b) #define ALL(a) (a).begin(), (a).end() #define SZ(a) ((int)(a).size()) #define INF (0x3f3f3f3f) #define INF1 (2139062143) #define Mod (1000000007) #define debug(...) fprintf(stderr, __VA_ARGS__) #define y1 wozenmezhemecaia template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; } template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; } inline int read() { register int _, __; register char c_; for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1; for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48); return _ * __; } const int maxn = 2000005, maxw = 1005; int id[maxw][maxw][2], v[maxn * 3], nex[maxn * 3], beg[maxn], e, w[maxn * 3], n, tot; inline void add(int uu, int vv, int ww, int ty) { v[++ e] = vv, w[e] = ww, nex[e] = beg[uu], beg[uu] = e; if (ty) add(vv, uu, ww, 0); } inline int SPFA(int s, int t) { static queue<int> q; static int dis[maxn], vis[maxn]; For(i, 1, tot) dis[i] = INF; dis[s] = 0, q.push(s); while (!q.empty()) { register int u = q.front(); q.pop(), vis[u] = 0; for (register int i = beg[u]; i; i = nex[i]) if (chkmin(dis[v[i]], dis[u] + w[i])) if (!vis[v[i]]) q.push(v[i]), vis[v[i]] = 1; } return dis[t]; } int main() { #ifdef hany01 File("bzoj1001"); #endif n = read(); static int m = read(), S, T; if (n == 1 || m == 1) { static int Min = INF; For(i, 1, max(n, m) - 1) chkmin(Min, read()); printf("%d\n", Min); return 0; } For(i, 1, n - 1) For(j, 1, m - 1) id[i][j][0] = ++ tot, id[i][j][1] = ++ tot; S = ++ tot, T = ++ tot; For(i, 1, n) For(j, 1, m - 1) { register int u = id[i - 1][j][0], v = id[i][j][1]; if (!u) u = T; else if (!v) v = S; add(u, v, read(), 1); } For(i, 1, n - 1) For(j, 1, m) { register int u = id[i][j - 1][1], v = id[i][j][0]; if (!u) u = S; else if (!v) v = T; add(u, v, read(), 1); } For(i, 1, n - 1) For(j, 1, m - 1) add(id[i][j][0], id[i][j][1], read(), 1); printf("%d\n", SPFA(S, T)); return 0; } //庭樹不知人去盡,春來還發舊時花。 // -- 岑參《山房春事二首》

相關推薦

BZOJ1001BJOI2006兔子對偶短路

Description 現在小朋友們最喜歡的”喜羊羊與灰太狼”,話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形:

BJOI 2006兔子對偶

題目連結 題解 明顯是求給定的圖的最小割。 但是如果直接跑最大流的話會爆炸。 我們發現這個圖有一個性質:它是一個平面圖(可平面圖)。 我們考慮構造它的對偶圖,因為對偶圖的最短路即是

BZOJ1001兔子平面圖轉對偶短路小割

題面 BZOJ 洛谷 題解 這題用最小割可以直接做 今天再學習了一下平面圖轉對偶圖的做法 大致的思路如下: 1.將源點到匯點中再補一條不與任何線段有交點的邊。這條邊把外側無限大的區域劃

UOJ277清華集訓2016定向越野計算幾何短路

UOJ題目傳送門 顯然最優的路徑只會經過若干條兩個圓的公切線和若干段圓弧 為了方便,把起點終點看成兩個半徑為\(0\)的圓也行。 最煩的就是算兩個圓的公切線了,一共有四條 對於靠外面的兩條,我們把切線、半徑和兩圓心之間的線段連起來,會構成一個直角梯形。 我們可以求出兩圓心連線的傾斜角,進而求出這兩條

BZOJ1001Beijing2006兔子平面圖轉對偶小割+短路

題目描述 傳送門 題解 題目描述很明顯這就是一道最小割,不過跑最大流的話會TLE。 我們發現這是一個平面圖(什麼是平面圖?),那麼我們就可以參考平面圖轉對偶圖的思想,將這道題轉化成最短路。

BZOJ 1001兔子大流

ron define max \n 效率 cpp cstring inf tchar 題目鏈接 最大流裸題,沒什麽好說吧,恰好點數多,考驗網絡流的效率,正好練\(Dinic\)。 #include <cstdio> #include <queue>

51Nod - 1094和為k的連續區間 字首和二分查詢

題幹: 一整數數列a1, a2, ... , an(有正有負),以及另一個整數k,求一個區間i,ji,j,(1 <= i <= j <= n),使得aii + ... + ajj = k。 Input 第1行:2個數N,K。N為數列的長度。K為需

BZOJ 1922SDOI 2010大陸爭霸有限制的短路

(誰告訴我這是個分層最短路來著的???) 進入一個城市必須要這個城市所有結界都打破才能進 那我們可以邊炸邊走 也就是說 我們可以維護d1陣列:走到的時間(結界可能沒炸完) d2陣列:可進入的時間(結界都被炸完了) d陣列:真實的到達時間 容易發現d[i]=max(d1[i],d2[2]) 那我們就用dijks

matlab雷達成像系列 之 RMRange Migration距離遷徙成像演算法

本章內容 重點 •SAR成像幾何關係;SAR回波模型;SAR成像模型; •RD成像演算法;SAR成像質量; •距離徙動;距離校正; •實時成像;回波模擬; 要求 •掌握SAR回波

洛谷 P2900 [USACO08MAR]土地征用Land Acquisition斜率優化單調棧

答案 print ++ name printf tdi max tail ++i 題目鏈接 雙倍經驗 設\(H\)表示長,\(W\)表示寬。 若\(H_i<H_j\)且\(W_i<W_j\),顯然\(i\)對答案沒有貢獻。 於是把所有點按\(H\)排序,然後依次

[BJOI2006]兔子網絡流

地形 道路 urn pri cout 第三部分 第二部分 void struct 題目描述 現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的,而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的

BZOJ1001 [BeiJing2006]兔子 平面圖轉對偶小割轉短路

bits ges code inf 如果 對偶圖 += ron oid 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 28885 Solved: 7540[Submit

洛谷P4001 [BJOI2006]兔子平面圖轉對偶

bool .html next fine pri n) www moto tdi 傳送門 明明只要最小割加點優化就能過的東西…… 然而我偏偏要去學平面圖轉對偶圖結果發現課件關鍵地方看不清->這裏 而且建圖累的半死…

BZOJ1001:兔子小割大流+vector模板

cout 地形 ++ 能夠 can 圖片 jpg http img 1001: [BeiJing2006]狼抓兔子 Description 現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的,而且現在的兔子還比較笨,它們只有兩個窩,現在

bzoj1001: [BeiJing2006]兔子大流

題目傳送門 解法: 每一隻兔子就需要一隻狼。 那麼我們只需要求出最多能通過多少隻兔子即可。 然後就派多少隻狼就行了唄。。 因為兔子從哪裡過來的我就在哪裡放狼。 所以狼的數量一定等於最多兔子通過的數量 題目並不要求求方案,所以不需知道兔子從哪過來。

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

BZOJ 1001 兔子網絡流

end init false bzoj algo syn i++ vector std 題解:這個建圖很簡單,只要把(1,1)這個點作為超級源,(n,m)作為超級源就可以xjbp。空間要算好。dinic當前弧優化一下就可以跑1500ms #include <io

兔子 HYSBZ - 1001(網路流/平面圖轉對偶短路)

傳送門 題意:有個方格,求從(1,1)到(n,m)的最小割 題解:有兩種方法,第一種:使用dinic演算法,但是需要有個優化就是當每次增廣時,如果一旦哪條路增廣失敗,那麼就把這條路直接賦值為-1,把它堵死,這樣優化可以達到很高。 附上第一種程式碼:(使用白書上的dinic演算法呢,可以過

dinic模板BZOJ1001 兔子

#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace st