最小斯坦納樹的模板題
傳送門
1view code//achen
2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include10 #include
11 #include12
#define formylove return 0
13#define for(i,a,b) for(int i=(a);i<=(b);i++)
14#define rep(i,a,b) for(int i=(a);i>=(b);i--)
15const
int n=1050
;16 typedef long
long
ll;17 typedef double
db;18
using
namespace
std;
19int n,m,a[12][12],tot,sx,sy,f[12][12
][n];
2021 templatevoid read(t &x)
2728
struct
pre
31 }p[12][12
][n];
32#define pr pair33
#define fi first
34#define se second
3536 queueque;
37int vis[12][12],tx[5]=,ty[5]=;
38void spfa(int
s) 52}53
}54}55
56void dfs(int x,int y,int
s) 64
65int
main() 80}
81int up=(1
<1
;82 for(s,0
,up)
89if(f[i][j][s]!=inf) 93}
94spfa(s);95}
96 printf("
%d\n
",f[sx][sy][up]);
97dfs(sx,sy,up);
98 for(i,1,n) for(j,1
,m)
104formylove;
105 }
最近bug真的好多啊,難得1a。
每次看以前忘了的模板的時候看到自己部落格就模板題三個字的時候就很想打自己。所以我得口胡兩句。
完全不嚴謹的口胡:
最小斯坦納樹大概是網格圖求乙個給定點集的最小網路,並且允許在給定點集之外選擇一些點。
一般k很小,k<=10的樣子,可以用狀壓dp求解。
f[i][s]表示以點i為根,已和s集合裡的點聯通的生成樹的最小代價。
兩種轉移,
1、i的不同子樹的合併,f[i][s]=min;
2、考慮新增給定子集外的點的情況,f[i][s]=f[j][s]+a[i][j]; 從一棵合法的樹乙個點乙個點向外擴張,
比如這棵樹,褐色是給定點集,下面兩個褐色點聯通後從中間的紅點向上擴張,在最上面的褐點的位置再用第一種轉移合併即可得到以最上面的褐點為根的這棵樹。
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...