Luogu 4001 BJOI2006 狼抓兔子

2022-06-13 04:03:06 字數 1821 閱讀 3293

bzoj 1001……

並不會這個trick,所以筆記要詳細一點。

前置知識 : 平面圖轉對偶圖    傳送門

聽說直接$dinic$就好了,還跑得比正解快……

首先我們按照平面圖的定義,把網格圖中所有的平面以及另加的起點和終點在新圖中標號,一共有$(n - 1) * (m - 1) * 2 + 2$個點,標完樣例之後大概是這樣子的:

然後我們接著按照定義,把有相鄰的邊的點連上雙向邊,對於那些在邊界上的邊,我們分別選擇和$st$和$ed$連邊,具體來說是這樣的:

紅色的邊和$st$連邊,藍色的邊和$ed$連邊,其他黑色的邊和它相鄰的兩個聯通塊連邊。

注意$n == 1$或者$m == 1$的時候其實是一條鏈的情況,只要把最小的邊鴿掉就好了,這時候所有的邊都是要從$st$出發連到$ed$的,但是我的寫法會掛掉,所以需要拎出來特判一下。

容易發現這樣子構圖之後從$st$到$ed$的每一條路都對應了原圖中左上角到右下角的乙個鴿,這樣子我們求乙個最小鴿就變成了乙個最短路,就能方便地跑過去了。

要注意乙個細節就是說$st$和$ed$必須放在左下角和右上角(可以對調),因為我們在原圖中是要從左上角到右下角求乙個最小鴿,要不然就不代表從左上角到右下角的乙個最小鴿了吧。

連完邊之後的效果圖大概是這個大神部落格裡面的樣子。    戳這裡

時間複雜度$o(nmlognm)$。

code:

#include #include 

#include

#include

using

namespace

std;

typedef pair

pin;

const

int n = 2e6 + 5

;const

int m = 6e6 + 5

;int n, m, tot = 0

, head[n], dis[n];

bool

vis[n];

struct

edge e[m];

inline

void add(int

from, int to, int

val)

inline

void addedge(int x, int y, int

v) inline

void read(int &x)

priority_queue

q;inline

void dij(int

st) }}

}int

main()

for(int i = 1; i < n; i++)

for(int j = 1; j <= m; j++)

for(int i = 1; i < n; i++)

for(int j = 1; j < m; j++)

} else

for(int i = 1; i < n; i++)

for(int j = 1; j <= m; j++)

for(int i = 1; i < n; i++)

for(int j = 1; j < m; j++)

}dij(st);

printf(

"%d\n

", dis[ed]);

return0;

}

view code

P4001 BJOI2006 狼抓兔子

不少題解都是用網路流來做最小割 網路流是什麼 但對於乙個不會網路流的蒟蒻來做這題相當困難。聽機房daolao說可以重構圖做最短路。然後就baidu將平面圖轉換成乙個對偶圖,因為網路流的最小割 對偶圖的最短路,所以只要在對偶圖上跑最短路 從左上角跑到右下角 就行了。由於堆優化的dijkstra寫炸了,...

BJOI2006 狼抓兔子

現在小朋友們最喜歡的 喜羊羊與灰太狼 話說灰太狼抓羊不到,但抓兔子還是比較在行的,而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣乙個網格的地形 左上角點為 1,1 右下角點為 n,m 上圖中n 3,m 4 有以下三種型別的道路 1 x,y x 1,y 2 x,y x,y 1 3...

BJOI2006 狼抓兔子

求乙個網格圖的最小割。這個題一看就知道是乙個最小割模型,於是就快樂的打了dinic,也就快樂的tle了。查了查資料才知道,這個題要用到對偶圖的知識 平面圖最小割對應對偶圖最短路。所謂對偶圖,就是以原圖中的面作為點 將s,t連線以將無界區域分成兩部分 原圖中的邊在對偶圖中變為連線相鄰的面,於是,顯然對...