生活随笔
收集整理的這篇文章主要介紹了
Kruskal重构树
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
構(gòu)建方法
把生成樹的每個邊拆成一個點(diǎn)表示,點(diǎn)權(quán)即為原來的邊權(quán),添加兩個邊指向原來的點(diǎn)。這樣kruskalkruskalkruskal重構(gòu)樹就有2?n?12*n-12?n?1個點(diǎn)
性質(zhì)
- 葉子節(jié)點(diǎn)對應(yīng)之前的點(diǎn),非葉子節(jié)點(diǎn)對應(yīng)之前的邊
- 從葉子節(jié)點(diǎn)向上走邊權(quán)遞增(邊權(quán)升序建kruskal)
- 以節(jié)點(diǎn)KKK為根節(jié)點(diǎn)的子樹點(diǎn)權(quán)滿足邊權(quán)≤K\le K≤K
用處
- 最小瓶頸路(最長邊最小)QQQ次詢問
- 邊權(quán)不超過KKK的所有點(diǎn)對,以KKK為根節(jié)點(diǎn)的子樹
struct ac
{int u
, v
, w
;bool operator < (const ac
&t
) {return w
< t
.w
;}
}edge
[maxn
];
struct reset_kruskal
{struct ac
{int v
, nex
;}edge
[maxn
];int head
[maxn
], pre
[maxn
], cnt
, n
;int dep
[maxn
], vis
[maxn
], fa
[maxn
][31], weight
[maxn
];void init(int t
) {n
= t
;cnt
= 0;for (int i
= 0; i
<= n
; ++i
) pre
[i
] = i
;fill(head
, head
+n
+1, -1);fill(vis
, vis
+n
+1, 0);}void add(int u
, int v
) {edge
[cnt
] = {v
, head
[u
]};head
[u
] = cnt
++;} void dfs
(int u
) { vis
[u
] = 1;for (int i
= 1; i
<= log2(n
); ++i
) {if (fa
[u
][i
-1] == 0) break;fa
[u
][i
] = fa
[fa
[u
][i
-1]][i
-1];}for (int i
= head
[u
]; ~i
; i
= edge
[i
].nex
) {int v
= edge
[i
].v
;dep
[v
] = dep
[u
] + 1;fa
[v
][0] = u
; dfs(v
);}}int lca(int u
, int v
) {if (dep
[u
] < dep
[v
]) swap(u
, v
);int det
= dep
[u
] - dep
[v
];for (int i
= 0; i
<= log2(det
); ++i
) {if (det
& (1 << i
)) u
= fa
[u
][i
];}if (u
== v
) return u
;for (int i
= log2(dep
[u
]); i
>= 0; --i
) {if (fa
[u
][i
] != fa
[v
][i
]) {u
= fa
[u
][i
];v
= fa
[v
][i
];}}return fa
[u
][0];}int find
(int x
) {int t
= x
;while (x
!= pre
[x
]) x
= pre
[x
];while (t
!= pre
[t
]) {int fa
= pre
[t
];pre
[t
] = x
;t
= fa
;}return x
;}
}kru
;
總結(jié)
以上是生活随笔為你收集整理的Kruskal重构树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。