BZOJ 2595 Wc2008 遊覽計畫

2022-05-11 21:48:26 字數 1126 閱讀 1442

\(n * m\)的網格,如果\(a_ = 0\)則表示景點,否則表示這裡的需要的志願者人數。求一種安排志願者的方案使得所有景點連通且志願者最少。

本題可以插頭dp,然而有乙個東西叫斯坦納樹,來學習學習。

令\(f(i, j, s)\)表示\((i, j)\)為根,連通性為\(s\)的最少志願者。則有轉移:

$$f(i, j, s) = min

\begin

f(i, j, t) + f(i, j, s-t) - a_ & t \neq \varnothing, t \subset s \\

f(i', j', s) & (i, j)與(i', j')相鄰 \\

\end

$$第乙個轉移可以直接做,然而第二個轉移不是\(dag\)= =,所以我們得用最短路來求出來。

所以我們狀壓dp一下,然後每乙個狀態\(s\)先更新了第一種轉移,然後再最短路一下。

然後完了= =

如分析。

#include using namespace std;

const int n=10, m=n*n+5, oo=0x3f3f3f3f, dx=, dy=;

int n, m, a[n][n], f[n][n][1<=n || fy<0 || fy>=m)

int temp=f[x][y][s]+a[fx][fy];

if(f[fx][fy][s]>temp)

p[fx][fy][s]=hash(x, y, s);

}} vis[x][y]=0;

} fr=ta=0;

}void work()

}if(f[i][j][s]!=oo)

}} spfa(s); }}

void dfs(int i, int j, int s)

int y=h%100, x=(h%10000)/100, t=h/10000;

dfs(x, y, t);

if(i==x && j==y)

}void out()

} }}void prin()

else if(ok[i][j])

else

} puts(""); }}

int main()

BZOJ 2595 Wc2008 遊覽計畫

啊 斯坦納樹 好像很厲害啊 反正我之前不會。其實不知道實用性怎麼樣 畢竟複雜度不小。大概過程就是乙個狀壓dp spfa 列舉狀態 從小狀態更新大狀態 再對當前狀態做一次像spfa一樣的鬆弛操作 下面這個人講的不錯 可以去看看 為什麼我的 又那麼短 有點擔心優美度了 有誰提一下建議嗎2333 我覺得還...

BZOJ 2595 Wc2008 遊覽計畫

n m 的網格,如果 a 0 則表示景點,否則表示這裡的需要的志願者人數。求一種安排志願者的方案使得所有景點連通且志願者最少。本題可以插頭dp,然而有乙個東西叫斯坦納樹,來學習學習。令 f i,j,s 表示 i,j 為根,連通性為 s 的最少志願者。則有轉移 f i,j,s min begin f ...

bzoj2595 Wc2008 遊覽計畫

斯坦納樹 f i zt 表示以i為根,連成的聯通塊包括那些景點 兩個轉移 f i zt f i tzt f i zt tzt a i f i zt f j zt a i i,j 相鄰 後面這個可以用spfa優化 記得先進行前乙個轉移,還有容斥減掉a i include include include...