UVA - 11354 Bond (最小生成树+带权并查集)

题意:多组询问,每组询问求无向图中两个结点间最小瓶颈路的最大边权

算是带权并查集的一道板子题吧,首先用kruskal算法构建最小生成树,构建过程中并查集按秩合并,同时每个点记录一个cost值,表示把该点与父亲结点合并所需的最小代价,那么两点间最小瓶颈路的最大边权就是带权并查集上两点之间路径的最大边权,用类似求LCA的方法自底向上跳就可以求出

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=1e5+10,inf=0x3f3f3f3f;
 5 int n,m,fa[N],siz[N],cost[N],Q,ka;
 6 struct E {
 7     int u,v,c;
 8     bool operator<(const E& b)const {return c<b.c;}
 9 } e[N];
10 int fd(int x) {return fa[x]?fd(fa[x]):x;}
11 void mg(int x,int y,int c) {
12     if((x=fd(x))==(y=fd(y)))return;
13     if(siz[x]>siz[y])swap(x,y);
14     fa[x]=y,siz[y]+=siz[x],cost[x]=c;
15 }
16 void kruskal() {
17     for(int i=1; i<=n; ++i)fa[i]=0,siz[i]=1;
18     sort(e+1,e+1+m);
19     for(int i=1; i<=m; ++i) {
20         int u=e[i].u,v=e[i].v,c=e[i].c;
21         mg(u,v,c);
22     }
23 }
24 int qry(int u,int v) {
25     int ret=0;
26     while(u!=v) {
27         if(siz[u]>siz[v])swap(u,v);
28         ret=max(ret,cost[u]);
29         u=fa[u];
30     }
31     return ret;
32 }
33 
34 int main() {
35     while(~scanf("%d%d",&n,&m)) {
36         if(ka++)puts("");
37         for(int i=1; i<=m; ++i)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);
38         kruskal();
39         scanf("%d",&Q);
40         while(Q--) {
41             int u,v;
42             scanf("%d%d",&u,&v);
43             printf("%d\n",qry(u,v));
44         }
45     }
46     return 0;
47 }

 

posted @ 2021-04-05 11:26  jrltx  阅读(53)  评论(0编辑  收藏  举报