题目:luogu1967.
题目大意:A国有
n
n
n座城市,编号从
1
1
1到
n
n
n,城市之间有
m
m
m条双向道路.每一条道路对车辆都有重量限制(限重).现在有
q
q
q辆货车在运输货物,司机们想知道每辆车在不超过车辆限制的情况下,最多能运多重的货物.
1
≤
n
<
1
0
4
,
1
≤
m
<
5
∗
1
0
4
,
1
≤
q
<
3
∗
1
0
4
1\leq n<10^4,1\leq m<5*10^4,1\leq q<3*10^4
1≤n<104,1≤m<5∗104,1≤q<3∗104.
这道题暴力30分就可以直接跑spfa来做.
考虑对于每一条路径可以运输的最重的货物重量是路径上最小的边权,发现这个性质后就可以想到图的最大生成树也有这个性质,于是就考虑求出最大生成树后在最大生成树上跑出每条路径的最小边权.
树的链上查询是非常经典的问题,发现这道题并没有修改,所以直接用倍增处理就好了.
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int M=500000,N=10000,C=19,INF=(1<<31)-1;
int n,m,q;
struct graph_side{
int x,y,v;
bool operator < (const graph_side &p)const{return v>p.v;}
}ec[M+9];
int fa[N+9];
int get(int u){return u==fa[u]?u:fa[u]=get(fa[u]);}
struct tree_side{
int y,v,next;
}e[N*2+9];
int top,lin[N+9];
void ins(int x,int y,int v){
e[++top].y=y;e[top].v=v;
e[top].next=lin[x];
lin[x]=top;
}
void kruskal(){
sort(ec+1,ec+1+m);
for (int i=1;i<=n;++i) fa[i]=i;
int x,y;
for (int i=1;i<=m;++i){
x=get(ec[i].x);y=get(ec[i].y);
if (x==y) continue;
fa[x]=y;
ins(ec[i].x,ec[i].y,ec[i].v);
ins(ec[i].y,ec[i].x,ec[i].v);
}
}
int gr[N+9][C+1],minn[N+9][C+1],deep[N+9],r[N+9];
void dfs(int k,int fa){
deep[k]=deep[fa]+1;
gr[k][0]=fa;
for (int i=1;i<=C;++i){
gr[k][i]=gr[gr[k][i-1]][i-1];
minn[k][i]=min(minn[k][i-1],minn[gr[k][i-1]][i-1]);
}
for (int i=lin[k];i;i=e[i].next)
if (e[i].y^fa){
minn[e[i].y][0]=e[i].v;
r[e[i].y]=r[k];
dfs(e[i].y,k);
}
}
int Query(int x,int y){
int ans=INF;
if (deep[x]<deep[y]) swap(x,y);
for (int i=C;i>=0;--i)
if (deep[gr[x][i]]>=deep[y]){
ans=min(ans,minn[x][i]);
x=gr[x][i];
}
if (x==y) return ans;
for (int i=C;i>=0;--i)
if (gr[x][i]^gr[y][i]){
ans=min(ans,min(minn[x][i],minn[y][i]));
x=gr[x][i];y=gr[y][i];
}
return min(min(minn[x][0],minn[y][0]),ans);
}
Abigail into(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
scanf("%d%d%d",&ec[i].x,&ec[i].y,&ec[i].v);
}
Abigail work(){
kruskal();
for (int i=1;i<=n;++i)
if (!deep[i]) r[i]=i,dfs(i,0);
}
Abigail getans(){
int x,y;
scanf("%d",&q);
for (int i=1;i<=q;++i){
scanf("%d%d",&x,&y);
printf("%d\n",r[x]^r[y]?-1:Query(x,y));
}
}
int main(){
into();
work();
getans();
return 0;
}