版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zz_ylolita/article/details/82821709
在做最小生成树的时候,使用并查集的按秩合并,不会破坏树的结构,复杂度O(logn)
#include <bits/stdc++.h>
using namespace std;
#define INF 1000000009
#define N 50010
int n,m,q,x,y;
int fa[N],Rank[N],edge[N],c[N];
struct node
{
int x,y,z;
}a[100010];
int cmp(node a, node b)
{
return a.z < b.z;
}
int Find(int x)
{
return fa[x] == x ? x:Find(fa[x]);
}
void Kruscal()
{
int s = 0,f1,f2;
for (int i=1;i<=n;i++) fa[i] = i, Rank[i] = 1;
memset(edge, 0, sizeof(edge));
for (int i=1;i<=m;i++)
{
f1 = Find(a[i].x);
f2 = Find(a[i].y);
if (f1 != f2)
{
if (Rank[f1] < Rank[f2])
{
fa[f1] = f2;
edge[f1] = a[i].z;
Rank[f2] = max(Rank[f2], Rank[f1]+1);
}
else
{
fa[f2] = f1;
edge[f2] = a[i].z;
Rank[f1] = max(Rank[f1], Rank[f2]+1);
}
s++;
}
if (s == n-1) break;
}
}
int query(int x, int y)
{
for (int i=1;i<=n;i++) c[i] = -1;//表示从x往上走走到i的时候路径的最大值
int tmp = 0, ans = 0;
while (1)
{
c[x] = tmp;
if (fa[x] == x) break;
tmp = max(tmp, edge[x]);
x = fa[x];
}
while (1)
{
if (c[y] >= 0){ans = max(ans,c[y]);break;}//走到了x和y的LCA的位置了
if (fa[y] == y) break;
ans = max(ans, edge[y]);
y = fa[y];
}
return ans;
}
int main()
{
bool flag = 0;
while (~scanf("%d%d", &n, &m))
{
if (flag) printf("\n");
for (int i=1;i<=m;i++)
scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z);
sort(a+1,a+m+1,cmp);
Kruscal();
scanf("%d", &q);
for (int i=1;i<=q;i++)
{
scanf("%d%d", &x, &y);
printf("%d\n", query(x,y));
}
flag = 1;
}
}