【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;
}
//庭樹不知人去盡,春來還發舊時花。
// -- 岑參《山房春事二首》
相關推薦
【BZOJ1001】【BJOI2006】狼抓兔子(對偶圖,最短路)
Description 現在小朋友們最喜歡的”喜羊羊與灰太狼”,話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形:
【BJOI 2006】狼抓兔子(對偶圖)
題目連結 題解 明顯是求給定的圖的最小割。 但是如果直接跑最大流的話會爆炸。 我們發現這個圖有一個性質:它是一個平面圖(可平面圖)。 我們考慮構造它的對偶圖,因為對偶圖的最短路即是
【BZOJ1001】狼抓兔子(平面圖轉對偶圖,最短路,最小割)
題面 BZOJ 洛谷 題解 這題用最小割可以直接做 今天再學習了一下平面圖轉對偶圖的做法 大致的思路如下: 1.將源點到匯點中再補一條不與任何線段有交點的邊。這條邊把外側無限大的區域劃
UOJ277【清華集訓2016】定向越野(計算幾何,最短路)
UOJ題目傳送門 顯然最優的路徑只會經過若干條兩個圓的公切線和若干段圓弧 為了方便,把起點終點看成兩個半徑為\(0\)的圓也行。 最煩的就是算兩個圓的公切線了,一共有四條 對於靠外面的兩條,我們把切線、半徑和兩圓心之間的線段連起來,會構成一個直角梯形。 我們可以求出兩圓心連線的傾斜角,進而求出這兩條
【BZOJ1001】【Beijing2006】狼抓兔子(平面圖轉對偶圖:最小割+最短路)
題目描述 傳送門 題解 題目描述很明顯這就是一道最小割,不過跑最大流的話會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 1922】【SDOI 2010】大陸爭霸(有限制的最短路)
(誰告訴我這是個分層最短路來著的???) 進入一個城市必須要這個城市所有結界都打破才能進 那我們可以邊炸邊走 也就是說 我們可以維護d1陣列:走到的時間(結界可能沒炸完) d2陣列:可進入的時間(結界都被炸完了) d陣列:真實的到達時間 容易發現d[i]=max(d1[i],d2[2]) 那我們就用dijks
【matlab】雷達成像系列 之 RM(Range 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