BZOJ 2595 WC 2008 遊覽計畫

2022-05-11 22:17:45 字數 1212 閱讀 2140

斯坦納樹的例題誒。。。我怎麼做了好長時間_(:з」∠)_

首先這是一棵樹。

狀壓表示狀態,\(f(i,j,s)\)表示連通的景點的狀態為s,i和j為樹根的最小值。

轉移時先在當前狀態s上列舉s的子集t,用子集來轉移\(f(i,j,s)=min\,t\varsubsetneqq s,t\neq\varnothing\)

順便把所有可以用來更新的狀態加入佇列,然後在當前列舉這層列舉的s內做spfa,求出其他點的f值。

因為最優解一定可以通過兩個沒有重疊方塊的連通塊合併,所以不用擔心求出的解會有方塊被算多次。

時間複雜度\(o(2^kn^2m^2)\)。

#include#include#include#define mk(x, y, z) ((x) + (y) * 100 + (z) * 10000)

using namespace std;

int a[13][13], f[13][13][1 << 10], pre[13][13][1 << 10], n, m, q[1000003], head, tail, inf, tot = 0, ans = 0x7fffffff;

bool inq[10003], mark[13][13];

const int dx[4] = ;

const int dy[4] = ;

void spfa(int s)

}} }

}void dfs(int x, int y, int s)

}void ouit(int totnum)

}int main()

} int totnum = (1 << tot) - 1, now;

for (int s = 1; s <= totnum; ++s)

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

inq[q[++tail] = mk(i, j, 0)] = true;

} spfa(s); }

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

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

ans = min(ans, f[i][j][totnum]);

printf("%d\n", ans);

ouit(totnum);

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

return 0;

}

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...