还是纪念一下
傻逼题
题意
A 国有 nn 座城市,编号从 11 到 nn,城市之间有 mm 条双向道路。每一条道路对车辆都有重量限制,简称限重。
现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
正解
显然走的边在最大生成树上
然后感觉是换根DP
但是
min
\min
min抠不掉
l
c
a
lca
lca到根
换个思路:直接求
l
c
a
lca
lca,在求
L
C
A
LCA
LCA的时候取
min
\min
min
取
min
\min
min的时候顺序写反了😭
感谢young_Zn_Cu大佬给我debug
友链在我的自我介绍里
#include<bits/stdc++.h>
using namespace std;
#define in Read()
#define int long long
int in{
int i=0,f=1;char ch=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
const int N=4e4+5;
const int INF=1e6;
int n,m,q,fa[N],tot;
int first[N],nxt[N<<1],aim[N<<1],wei[N<<1];
int f[N][25],w[N][25],dep[N];
bool vis[N];
struct Edge{
int u,v,w;
Edge(){}
Edge(int _u,int _v,int _w){
u=_u,v=_v,w=_w;
}
friend bool operator < (Edge e,Edge f){
return e.w<f.w;
}
}edge[N];
int get(int x){return fa[x]==x?x:fa[x]=get(fa[x]);}
void ljb(int u,int v,int w){
++tot;
nxt[tot]=first[u];
first[u]=tot;
aim[tot]=v;
wei[tot]=w;
return;
}
void print_tree(int u,int fa){
printf("%lld %lld\n",u,fa);
for(int e=first[u];e;e=nxt[e]){
int v=aim[e];
if(v==fa) continue;
print_tree(v,u);
}
}
void Kruscal(){
for(int e=m;e>=1;--e){
int u=edge[e].u,v=edge[e].v;
if(get(u)!=get(v)){
fa[get(u)]=get(v);
ljb(u,v,edge[e].w);
ljb(v,u,edge[e].w);
}
}
return;
}
void DFS(int u,int fa){
vis[u]=true;
f[u][0]=fa;
dep[u]=dep[fa]+1;
for(int e=first[u];e;e=nxt[e]){
int v=aim[e];
if(vis[v]) continue;
if(v==fa) continue;
w[v][0]=wei[e];
DFS(v,u);
}
return;
}
int lca(int u,int v){
int r=INF;
if(dep[u]<dep[v]) swap(u,v);
for(int l=20;l>=0;--l)
if(dep[f[u][l]]>=dep[v]){
// printf("%d %d\n",u,w[u][l]);
r=min(r,w[u][l]);
u=f[u][l];
}
if(u==v) return r;
for(int l=20;l>=0;--l)
if(f[u][l]^f[v][l])
r=min(r,min(w[u][l],w[v][l])),
u=f[u][l],v=f[v][l];
r=min(r,min(w[u][0],w[v][0]));
return r;
}
signed main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
n=in,m=in;
for(int i=1;i<=m;++i){
int u=in,v=in,w=in;
edge[i]=Edge(u,v,w);
}
sort(edge+1,edge+m+1);
for(int i=1;i<=n;++i)
fa[i]=i;
Kruscal();
for(int i=1;i<=n;++i)
if(!vis[i]){
f[i][0]=i;
w[i][0]=INF;
DFS(i,0);
}
for(int i=1;i<=n;++i) cerr<<i<<' '<<dep[i]<<endl;
for(int l=1;l<=20;++l)
for(int u=1;u<=n;++u){
f[u][l]=f[f[u][l-1]][l-1];
w[u][l]=min(w[u][l-1],w[f[u][l-1]][l-1]);
}
// for(int u=1;u<=n;++u){
// for(int l=0;l<20;++l)
// printf("%d ",w[u][l]);
// puts("");
// }
q=in;
for(int i=1;i<=q;++i){
int u=in,v=in;
if(get(u)^get(v))
puts("-1");
else
printf("%lld\n",lca(u,v));
}
// print_tree(1,0);
return 0;
}