斯坦納樹的例題誒。。。我怎麼做了好長時間_(:з」∠)_
首先這是一棵樹。
狀壓表示狀態,\(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...