Bond

题目链接

Bond

给定一张 \(n\) 个点 \(m\) 条边的无向图,每条边有一个权值,有 \(q\) 个询问,每次询问给出两个点 \((s,t)\),找到从一条从 \(s\)\(t\) 的路径,使得最大权值最小,只需输出这个权值

解题思路

最小生成树,ST,树链剖分,并查集按秩合并,最小瓶颈生成树,kruskal重构树

首先,可以肯定一点,这条路径一定可以是最小生成树上的一条唯一路径
定理:最小生成树是最小瓶颈生成树,但是最小瓶颈生成树不一定是最小生成树

可利用 kruskal 算法求出最小生成树,再利用和 \(LCA\) 类似的思想求出最小生成树上两点之间的最大权值,或者求树上两点之间的最大值可利用树链剖分(树链剖分只是一种思想,可用线段树或 \(st\) 表来实现)来求,或者可以用 tarjan 离线求解,另外还可以kruskal重构树,答案即为重构树两点之间的 lca

当然,在利用并查集求最小生成树时可以按秩合并,这样整棵树的高度为 \(O(logn)\) 级别,这样只需要从 \(s\) 开始回溯并记录到该节点的最大值,然后从 \(t\) 开始回溯,如果遇到标记,该标记如果为根节点,说明两个点不在一条链上,则取记录到该节点的较大值;否则在一条链上仍取较大值,因为如果 \(t\) 位于 \(s\) 下面,遇到标记时说明 \(t\)\(s\) 的路径已经走过了,否则如果 \(t\) 位于 \(s\) 上面,则一开始就回溯,答案即为到 \(t\) 的最大值

\(\color{red}{并查集按秩合并虽然没破坏树形结构,但最后形成的树也不是最小生成树,为什么可以直接按最小生成树操作?}\)

由于边权是按从小到大排序的,每次合并时大的边权都集中在深度较低的位置,由于计算的是最大权值,即使向上回溯时有些边权没有统计到,但大的边权一定会统计到,所以不会对答案造成影响

  • 时间复杂度:\(O(mlogm+qlogn)\)

tarjan:

  • 时间复杂度:\(O(mlogm+q)\)

树链剖分(线段树):

  • 时间复杂度:\(O(mlogm+qlog^2n)\)

树链剖分(st):

  • 时间复杂度:\(O(mlogm+qlogn)\)

kruskal 重构树:

  • 时间复杂度:\(O(mlogm+q)\)

代码

  • tarjan
// Problem: Bond
// Contest: Virtual Judge - UVA
// URL: https://vjudge.net/problem/UVA-11354
// Memory Limit: 1024 MB
// Time Limit: 8000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=5e4+5,M=1e5+5;
int n,m,q,h[N],fa[N],up[N],res[M],w[N];
vector<PII> adj[N];
vector<PII> query[N];
PII ask[M];
vector<int> ids[N];
bool vis[N];
struct A
{
	int x,y,w;
	bool operator<(const A &o)
	{
		return w<o.w;
	}
}a[M];
void merge(int x,int y)
{
	if(h[x]<h[y])fa[x]=y;
	else
	{
		fa[y]=x;
		if(h[x]==h[y])h[x]++;
	}
}
int find(int x)
{
	return x==fa[x]?x:fa[x]=find(fa[x]);
}
int get(int x)
{
	if(x==fa[x])return x;
	int t=get(fa[x]);
	up[x]=max(up[x],up[fa[x]]);
	return fa[x]=t;
}
void kruskal()
{
	sort(a+1,a+1+m);
	int cnt=0;
	for(int i=1;i<=m;i++)
	{
		int x=a[i].x,y=a[i].y,w=a[i].w;
		int tx=x,ty=y;
		x=find(x),y=find(y);
		if(x==y)continue;
		cnt++;
		merge(x,y);
		adj[tx].emplace_back(ty,w);
		adj[ty].emplace_back(tx,w);
		if(cnt>=n-1)break;
	}
}
void add_query(int u,int v,int id)
{
	query[u].emplace_back(v,id);
	query[v].emplace_back(u,id);
}
void tarjan(int u,int father)
{
	up[u]=0;
	for(auto t:adj[u])
	{
		int v=t.fi,w=t.se;;
		if(v==father)continue;
		tarjan(v,u);
		up[v]=w;
		fa[v]=u;
	}
	vis[u]=true;
	for(auto t:query[u])
	{
		int v=t.fi,id=t.se;
		if(vis[v])
			ids[get(v)].pb(id);
	}
	for(int id:ids[u])
	{
		int u=ask[id].fi,v=ask[id].se;
		get(u),get(v);
		res[id]=max(up[u],up[v]);
	}
}
int main()
{
	help;
	bool f=false;
    while(cin>>n>>m)
    {
    	if(f)puts("");
    	f=true;
    	for(int i=1;i<=n;i++)
    		fa[i]=i,ids[i].clear(),adj[i].clear(),query[i].clear(),up[i]=vis[i]=h[i]=0;
    	for(int i=1;i<=m;i++)cin>>a[i].x>>a[i].y>>a[i].w;
    	kruskal();
    	for(int i=1;i<=n;i++)fa[i]=i;
    	cin>>q;
    	for(int i=1;i<=q;i++)
    	{
    		cin>>ask[i].fi>>ask[i].se;
    		add_query(ask[i].fi,ask[i].se,i);
    	}
    	tarjan(1,0);    	
    	for(int i=1;i<=q;i++)
    	{
    		cout<<res[i]<<'\n';
    		res[i]=0;
    	}
    }
    return 0;
}
  • ST+并查集路径压缩+按秩合并(高度)
// Problem: Bond
// Contest: Virtual Judge - UVA
// URL: https://vjudge.net/problem/UVA-11354
// Memory Limit: 1024 MB
// Time Limit: 8000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
// #define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=5e4+5,M=1e5+5;
int n,m,q,s,t,tt,fa[N],h[N],d[N],f[N][20],mx[N][20];
vector<PII> adj[N];
struct A
{
	int a,b,w;
	bool operator<(const A &o)
	{
		return w<o.w;
	}
}a[M];
int find(int x)
{
	return x==fa[x]?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
	if(h[x]<h[y])
		fa[x]=y;
	else
	{
		fa[y]=x;
		if(h[x]==h[y])h[x]++;
	}
}
void kruskal()
{
	int cnt=0;
	sort(a+1,a+1+m);
	for(int i=1;i<=m;i++)
	{
		int x=a[i].a,y=a[i].b,w=a[i].w;
		int tx=x,ty=y;
		x=find(x),y=find(y);
		if(x==y)continue;
		cnt++;
		merge(x,y);
		adj[tx].pb({ty,w});
		adj[ty].pb({tx,w});
		if(cnt>=n-1)break;
	}
}
void bfs()
{
	queue<int> q;
	q.push(1);
	d[1]=1;
	while(q.size())
	{
		int x=q.front();
		q.pop();
		for(auto t:adj[x])
		{
			int y=t.fi,w=t.se;
			if(d[y])continue;
			d[y]=d[x]+1;
			f[y][0]=x;
			mx[y][0]=w;
			for(int i=1;i<=tt;i++)f[y][i]=f[f[y][i-1]][i-1],mx[y][i]=max(mx[y][i-1],mx[f[y][i-1]][i-1]);
			q.push(y);
		}
	}
}

int LCA(int x,int y)
{
	if(d[x]<d[y])swap(x,y);
	int res=0;
	for(int i=tt;i>=0;i--)
		if(d[f[x][i]]>=d[y])res=max(res,mx[x][i]),x=f[x][i];
	if(x==y)return res;
	for(int i=tt;i>=0;i--)
		if(f[x][i]&&f[x][i]!=f[y][i])res=max({res,mx[x][i],mx[y][i]}),x=f[x][i],y=f[y][i];
	return max({res,mx[x][0],mx[y][0]});
}
int main()
{
	help;
	int T=0;
    while(cin>>n>>m)
    {
    	for(int i=1;i<=n;i++)adj[i].clear(),h[i]=d[i]=0;
    	if(T)puts("");
    	T++;
    	tt=log(n)/log(2);
    	for(int i=1;i<=m;i++)cin>>a[i].a>>a[i].b>>a[i].w;
    	for(int i=1;i<=n;i++)fa[i]=i;
    	kruskal();
    	bfs();
    	cin>>q;
    	while(q--)
    	{
    		cin>>s>>t;
    		cout<<LCA(s,t)<<'\n';
    	}	
    }
    return 0;
}
  • 树链剖分(线段树)
// Problem: Bond
// Contest: Virtual Judge - UVA
// URL: https://vjudge.net/problem/UVA-11354
// Memory Limit: 1024 MB
// Time Limit: 8000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=5e4+5,M=1e5+5;
int n,m,x,y,d,q,s,t,fa[N],cnt,sz[N],son[N],pa[N],dep[N],top[N],nw[N],fw[N],id[N];
vector<PII> adj[N];
struct A
{
	int x,y,w;
	bool operator<(const A &o)
	{
		return w<=o.w;
	}
}a[M];
struct T
{
	int l,r;
	int mx;
}tr[4*N];
void pushup(int u)
{
	tr[u].mx=max(tr[u<<1].mx,tr[u<<1|1].mx);
}
void build(int u,int l,int r)
{
	tr[u]={l,r,0};
	if(l==r)
	{
		tr[u].mx=nw[l];
		return ;
	}
	int mid=l+r>>1;
	build(u<<1,l,mid),build(u<<1|1,mid+1,r);
	pushup(u);
}
int ask(int u,int l,int r)
{
	if(l<=tr[u].l&&tr[u].r<=r)return tr[u].mx;
	int res=0;
	int mid=tr[u].l+tr[u].r>>1;
	if(l<=mid)res=max(res,ask(u<<1,l,r));
	if(r>mid)res=max(res,ask(u<<1|1,l,r));
	return res;
}
int ask_path(int u,int v)
{
	int res=0;
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		res=max(res,ask(1,id[top[u]],id[u]));
		u=pa[top[u]];
	}
	if(u==v)return res;
	if(dep[u]>dep[v])swap(u,v);
	res=max(res,ask(1,id[son[u]],id[v]));
	return res;
}
int find(int x)
{
	return fa[x]==x?x:fa[x]=find(fa[x]);
}
void kruskal()
{
	sort(a+1,a+1+m);
	for(int i=1;i<=m;i++)
	{
		int x=a[i].x,y=a[i].y,w=a[i].w;
		int tx=x,ty=y;
		x=find(x),y=find(y);
		if(x!=y)
		{
			fa[x]=y;
			adj[tx].pb({ty,w}),adj[ty].pb({tx,w});
		}
	}
}
void dfs(int x,int fa,int depth)
{
	sz[x]=1,pa[x]=fa,dep[x]=depth,son[x]=0;
	for(auto t:adj[x])
	{
		int y=t.fi;
		if(y==fa)continue;
		fw[y]=t.se;
		dfs(y,x,depth+1);
		sz[x]+=sz[y];
		if(sz[son[x]]<sz[y])son[x]=y;
	}
}
void dfs1(int x,int tt)
{
	id[x]=++cnt,nw[cnt]=fw[x],top[x]=tt;
	if(!son[x])return ;
	dfs1(son[x],tt);
	for(auto t:adj[x])
	{
		int y=t.fi;
		if(y==son[x]||y==pa[x])continue;
		dfs1(y,y);
	}
}

int main()
{
    bool f=false;
    while(~scanf("%d%d",&n,&m))
    {
    	if(f)puts("");
    	f=true;
    	for(int i=1;i<=m;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
    	for(int i=0;i<=n;i++)adj[i].clear(),fa[i]=pa[i]=i;
    	kruskal();
    	cnt=-1;
    	dfs(1,0,1);
    	dfs1(1,1);
    	build(1,0,cnt);
    	cin>>q;
		while(q--)
		{
			scanf("%d%d",&s,&t);
			printf("%d\n",ask_path(s,t));	
		}
    }
    return 0;
}
  • 树链剖分(st表)
// Problem: Bond
// Contest: Virtual Judge - UVA
// URL: https://vjudge.net/problem/UVA-11354
// Memory Limit: 1024 MB
// Time Limit: 8000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=5e4+5,M=1e5+5;
int n,m,q,s,t,st[N][20],id[N],idx,sz[N],h[N],top[N],dep[N],son[N],fa[N],tt;
vector<PII> adj[N];
int find(int x)
{
	return x==fa[x]?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
	if(h[x]<h[y])
		fa[x]=y;
	else
	{
		fa[y]=x;
		if(h[x]==h[y])h[x]++;
	}
}
struct A
{
	int x,y,w;
	bool operator<(const A&o)
	{
		return w<o.w;
	}
}a[M];
void kruskal()
{
	sort(a+1,a+1+m);
	int cnt=0;
	for(int i=1;i<=m;i++)
	{
		int x=a[i].x,y=a[i].y,w=a[i].w;
		int tx=x,ty=y;
		x=find(x),y=find(y);
		if(x==y)continue;
		cnt++;
		merge(x,y);
		adj[tx].emplace_back(ty,w);
		adj[ty].emplace_back(tx,w);
		if(cnt>=n-1)break;
	}
}
void dfs(int x)
{
	sz[x]=1;
	son[x]=0;
	for(auto t:adj[x])
	{
		int y=t.fi;
		if(y==fa[x])continue;
		dep[y]=dep[x]+1;
		fa[y]=x;
		dfs(y);
		sz[x]+=sz[y];
		if(sz[son[x]]<sz[y])son[x]=y;	
	}
}
void dfs(int x,int tt)
{
	id[x]=++idx,top[x]=tt;
	if(son[x])dfs(son[x],tt);
	for(auto t:adj[x])
	{
		int y=t.fi,w=t.se;
		if(y!=fa[x]&&y!=son[x])
			dfs(y,y);
		if(y==fa[x])st[id[x]][0]=w;
	}
}
int ask_st(int l,int r)
{
	int k=log(r-l+1)/log(2);
	return max(st[l][k],st[r-(1<<k)+1][k]);
}
int ask(int u,int v)
{
	int res=0;
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		res=max(res,ask_st(id[top[u]],id[u]));
		u=fa[top[u]];
	}
	if(u==v)return res;
	if(dep[u]>dep[v])swap(u,v);
	res=max(res,ask_st(id[son[u]],id[v]));
	return res;
}
int main()
{
    help;
    bool f=false;
    while(cin>>n>>m)
    {
    	if(f)puts("");
    	f=true;
    	for(int i=1;i<=n;i++)adj[i].clear(),fa[i]=i;
    	for(int i=1;i<=m;i++)cin>>a[i].x>>a[i].y>>a[i].w;
    	tt=log(n)/log(2);
    	kruskal();
    	fa[1]=0;
    	dep[1]=1;
    	dfs(1);
    	idx=0;
    	dfs(1,1);
    	for(int j=1;j<=tt;j++)
    		for(int i=1;i+(1<<j-1)<=n;i++)
    			st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
    	cin>>q;
    	while(q--)
    	{
    		cin>>s>>t;
    		cout<<ask(s,t)<<'\n';
    	}
    }
    return 0;
}
  • 并查集按秩合并(大小)
// Problem: Bond
// Contest: Virtual Judge - UVA
// URL: https://vjudge.net/problem/UVA-11354
// Memory Limit: 1024 MB
// Time Limit: 8000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=5e4+5,M=1e5+5;
int n,m,x,y,d,q,s,t,fa[N],sz[N],e[N],vis[N];
struct A
{
	int x,y,w;
	bool operator<(const A &o)
	{
		return w<=o.w;
	}
}a[M];
int find(int x)
{
	return fa[x]==x?x:find(fa[x]);
}
void merge(int x,int y,int w)
{
	if(sz[x]<sz[y])
	{
		fa[x]=y;
		sz[y]+=sz[x];
		e[x]=w;
	}
	else
	{
		fa[y]=x;
		sz[x]+=sz[y];
		e[y]=w;
	}
}
void kruskal()
{
	sort(a+1,a+1+m);
	for(int i=1;i<=m;i++)
	{
		int x=a[i].x,y=a[i].y,w=a[i].w;
		x=find(x),y=find(y);
		if(x!=y)merge(x,y,w);
	}
}
void solve(int s,int t)
{
	for(int i=0;i<=n;i++)vis[i]=0;
	int res1=1,res2=0;
	int now=s;
	while(true)
	{
		vis[now]=res1;
		if(now==fa[now])break;
		res1=e[now];
		now=fa[now];
	}
	now=t;
	while(true)
	{
		if(vis[now])
		{
			res2=max(res2,vis[now]);
			break;
		}
		res2=e[now];
		now=fa[now];
	}
	cout<<res2<<'\n';
}
int main()
{
    help;
    bool f=false;
    while(cin>>n>>m)
    {
    	if(f)puts("");
    	f=true;
    	for(int i=1;i<=m;i++)cin>>a[i].x>>a[i].y>>a[i].w;
    	for(int i=0;i<=n;i++)fa[i]=i,sz[i]=1;
    	kruskal();
    	cin>>q;
		while(q--)
		{
			cin>>s>>t;
			solve(s,t);	
		}
    }
    return 0;
}
  • kruskal 重构树
// Problem: Bond
// Contest: Virtual Judge - UVA
// URL: https://vjudge.net/problem/UVA-11354
// Memory Limit: 1024 MB
// Time Limit: 8000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>

//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

template <typename T> bool chkMax(T &x, T y) {
    return (y > x) ? x = y, 1 : 0;
}
template <typename T> bool chkMin(T &x, T y) {
    return (y < x) ? x = y, 1 : 0;
}

template <typename T> void inline read(T &x) {
    int f = 1;
    x = 0;
    char s = getchar();

    while (s < '0' || s > '9') {
        if (s == '-')
            f = -1;

        s = getchar();
    }

    while (s <= '9' && s >= '0')
        x = x * 10 + (s ^ 48), s = getchar();

    x *= f;
}

const int N = 5e4 + 5, M = 1e5 + 5;
int n, m;
int w[N << 1], fa[N << 1], cnt, dfn[N << 2], pos[N << 1], time_stamp, d[N << 1];
int f[N << 2][20];
vector<int> adj[N << 1];
struct Tr {
    int l, r, w;
    bool operator<(const Tr &o)const {
        return w < o.w;
    }
} tr[M];
int find(int x) {
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void kruskal() {
    sort(tr + 1, tr + 1 + m);

    for (int i = 1; i <= m; i++) {
        int x = tr[i].l, y = tr[i].r;
        x = find(x), y = find(y);

        if (x != y) {
            w[++cnt] = tr[i].w;
            adj[cnt].pb(x), adj[cnt].pb(y);
            fa[x] = cnt, fa[y] = cnt;
        }
    }
}
void dfs(int x, int fa) {
    dfn[++time_stamp] = x;
    pos[x] = time_stamp;
    d[x] = d[fa] + 1;

    for (int y : adj[x])
        if (y != fa) {
            dfs(y, x);
            dfn[++time_stamp] = x;
        }
}
void init() {
    for (int i = 1; i <= time_stamp; i++)
        f[i][0] = dfn[i];

    int t = __lg(time_stamp);

    for (int j = 1; j <= t; j++)
        for (int i = 1; i + (1 << j) - 1 <= time_stamp; i++)
            if (d[f[i][j - 1]] < d[f[i + (1 << j - 1)][j - 1]])
                f[i][j] = f[i][j - 1];
            else
                f[i][j] = f[i + (1 << j - 1)][j - 1];
}
int ask(int x, int y) {
    int l = pos[x], r = pos[y];

    if (l > r)
        swap(l, r);

    int t = __lg(r - l + 1);

    if (d[f[l][t]] < d[f[r - (1 << t) + 1][t]])
        return w[f[l][t]];

    return w[f[r - (1 << t) + 1][t]];
}
int main() {
    help;
    bool f=false;
    while(cin>>n>>m)
    {
    	if(f)puts("");
    	f=true;
    	for(int i=1;i<=m;i++)cin>>tr[i].l>>tr[i].r>>tr[i].w;
    	for(int i=0;i<=2*n;i++)fa[i]=i,adj[i].clear();
    	cnt=n;
    	time_stamp=0;
    	kruskal();
    	dfs(cnt, 0);
    	init();
    	int q,s,t;
    	for(cin>>q;q;q--)
		{
			cin>>s>>t;
			cout<<ask(s,t)<<'\n';
		}
    }
    return 0;
}
posted @ 2022-04-24 23:54  zyy2001  阅读(98)  评论(0编辑  收藏  举报