n個點的一棵樹,增加了m條密道。對於樹上每條邊(a,
b)
(a,b)
(a,b
)被破壞後,要求a∼b
a\sim b
a∼b經過密道最短。
引理:對於每個道路被破壞,最多隻會經過一條邊。
證明:對於每個答案,被破壞後,所在層數低的點找到一條可以走出他的子樹的邊就好了,如果要走兩條邊,中間的點要不在子樹中,要不在子樹外。在子樹中直接那個點走就好了,在子樹外就不用再走了。證畢
所以我們就只需要找那一條密道就好了,我們考慮用並查集,先將密道長度排好,然後在每一條密道(x,
y,w)
(x,y,w)
(x,y,w
),就看一下x
xx和y
yy之前有沒有合併,如果有,就直接用那個答案,如果沒有,就合併,用新的答案。
#include
#include
#include
#define n 100010
using
namespace std;
struct nodea[n*2]
;struct linee[n]
;int ls[n]
,tot,x,y,w,ans,dep[n]
,father[n]
;int n,m,s,dfn[n]
,end[n]
,cnt,p[n]
,f[n]
,d[n]
;void
addl
(int x,
int y,
int w)
//加邊
bool
cmp(line x,line y)
void
dfs(
int x,
int fa)
//求深度和父節點,以及每個點對應來的編號
}intgf(
int x)
//查詢
void
doit
(int
&x,int y)
//合併
intmain()
for(
int i=
1;i<=m;i++
)scanf
("%d%d%d"
,&e[i]
.x,&e[i]
.y,&e[i]
.w);
dfs(1,
0);sort
(e+1
,e+m+
1,cmp)
;//排序
for(
int i=
1;i<=m;i++
)for
(int i=
1;i)printf
("%d\n"
,d[i]);
//輸出答案
}
並查集的實現(c ,利用map)
並查集 union find 是一種樹型的資料結構,用於處理一些不相交集合 disjoint sets 的合併及查詢問題。並查集存在兩個操作 1.union 聯合 2.finddeputy 查詢代表結點 和乙個需要解答的問題 issameset 是否 在乙個集合中,或者說是否有同乙個代表結點 利用m...
Kruskal演算法的C語言實現(並查集版)
問題 kruskal演算法求加權連通圖的最小生成樹的演算法。kruskal演算法總共選擇n 1條邊,所使用的貪婪準則是 從剩下的邊中選擇一條不會產生環路的具有最小耗費的邊加入已選擇的邊的集合中。注意到所選取的邊若產生環路則不可能形成一棵生成樹。kruskal演算法分e 步,其中e 是網路中邊的數目。...
C 求朋友圈的個數 並查集方法
有n個同學,他們之間有些是朋友,有些不是。友誼 是可以傳遞的,例如a和b是朋友,b和c是朋友,那麼a與c也是朋友 朋友圈就是完成 友誼 傳遞後的一組朋友。給定n n的矩陣代表同學間是否是朋友,如果m i j 1代表第i個學生與第j個學生是朋友,否則不是。求朋友圈的個數。例如 input 1,1,0 ...