题目链接:UVA-11354-Bond
首先,最大边最小的路径称为最小瓶颈路,最小瓶颈路一定是最小生成树上的路径(根据Kruskal)。
因此先处理处最小生成树,然后将最小生成树转化成一棵有根树。
anc[i][j]
为点
i
的第
cost[i][j]
为点
i
到
状态转移方程为:
anc[i][j]=anc[anc[i][j−1]][j−1]
cost[i][j]=max(cost[i][j−1],cost[anc[i][j−1]][j−1])
处理出
anc
和
cost
后,就可以很方便地查询了。
当查询
(u,v)
时,设
deep[u]>deep[v]
。
我们先把
u
提升到与
使用倍增即可。
然后将
u
和
在提升的过程中更新
ans
即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+7;
int n,m;
int fa[maxn];
int cost[maxn][20],anc[maxn][20],deep[maxn];
int k;
struct Edge
{
int u,v,d;
Edge(){}
Edge(int _v,int _d):v(_v),d(_d){}
bool operator < (const Edge & r) const
{
return d<r.d;
}
};
Edge e[maxn<<1];
vector<Edge> adj[maxn];
int f(int x)
{
return x==fa[x]?x:fa[x]=f(fa[x]);
}
bool Union(int x,int y)
{
x=f(x);y=f(y);
if(x==y) return false;
fa[x]=y;
return true;
}
void addedge(int u, int v, int d)
{
adj[u].push_back(Edge(v,d));
adj[v].push_back(Edge(u,d));
}
void dfs(int u,int pre,int deep)
{
::deep[u]=deep;
anc[u][0]=pre;
for(int i=0;i<adj[u].size();i++)
{
int v=adj[u][i].v;
if(v==pre) continue;
cost[v][0]=adj[u][i].d;
dfs(v,u,deep+1);
}
}
void init()
{
cost[1][0]=0;
k=0;
for(int j=1;(1<<j)<n;j++)
{
k=j;
for(int i=1;i<=n;i++)
{
anc[i][j]=-1;
int p=anc[i][j-1];
if(p==-1) continue;
anc[i][j]=anc[p][j-1];
cost[i][j]=max(cost[i][j-1],cost[p][j-1]);
}
}
}
int solve(int u,int v)
{
if(deep[u]<deep[v]) swap(u,v);
int ans=-1;
for(int i=k;i>=0;i--)
{
if(deep[u]-(1<<i)>=deep[v])
{
ans=max(ans,cost[u][i]);
u=anc[u][i];
}
}
if(u==v) return ans;
for(int i=k;i>=0;i--)
{
if(anc[u][i]!=-1&&anc[u][i]!=anc[v][i])
{
ans=max(ans,cost[u][i]);
ans=max(ans,cost[v][i]);
u=anc[u][i];
v=anc[v][i];
}
}
ans=max(ans,cost[u][0]);
ans=max(ans,cost[v][0]);
return ans;
}
int main()
{
ios::sync_with_stdio(false);
int s,t;
bool flag=false;
while(cin>>n>>m)
{
if(flag) cout << endl;
flag=true;
int u,v,d;
for(int i=0;i<m;i++)
cin>>e[i].u>>e[i].v>>e[i].d;
sort(e,e+m);
for(int i=1;i<=n;i++) adj[i].clear();
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=0;i<m;i++)
{
if(Union(e[i].u,e[i].v))
addedge(e[i].u,e[i].v,e[i].d);
}
dfs(1,-1,0);
init();
int q;
cin>>q;
while(q--)
{
cin>>u>>v;
cout << solve(u,v) << endl;
}
}
return 0;
}