「NOIP 2013」 货车运输
题目链接
\(Solution\)
这一道题直接用\(kruskal\)重构树就好了,这里就不详细解释\(kruskal\)重构树了,如果不会直接去网上搜就好了.接下来讲讲详细过程.
- 首先构建\(kruskal\)重构树.
- 对于询问直接求\(lca\)就可以了,如果没有\(lca\)输出\(-1\),否则输入\(lca\)上的权值就好了,不是很难.
\(Code\)
#include<bits/stdc++.h>
using namespace std;
const int N=200011;
int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return f*x;
}
struct node1 {
int to,next;
}e[500001];
struct node{
int x,y,v;
}b[N];
int res,cnt,n,m,t,pre[N],head[N],vis[N];
int f[N][21],dep[N],val[N],bin[101];
void add(int x,int y){ e[++cnt].to=y,e[cnt].next=head[x],head[x]=cnt; }
int find(int x){ return pre[x]==x?x:pre[x]=find(pre[x]); }
bool cmp(const node & a , const node & b ){ return a.v>b.v; }
void dfs(int k){
vis[k]=1;
for(int j=1;j<=19;j++)
f[k][j]=f[f[k][j-1]][j-1];
for(int i=head[k];i;i=e[i].next){
int v=e[i].to;
f[v][0]=k,dep[v]=dep[k]+1;
dfs(v);
}
}
int lca(int x,int y){
if(dep[x]<dep[y])
swap(x,y);
// cout<<dep[x]<<" "<<dep[y];
for(int i=19;i>=0;i--)
if(dep[x]-(1<<i)>=dep[y])
x=f[x][i];
if(x==y)
return y;
for(int i=19;i>=0;i--){
if(f[x][i]==f[y][i]||!f[y][i]||!f[x][i])
continue;
x=f[x][i],y=f[y][i];
}
return f[x][0];
}
void build(){
res=n,sort(b+1,b+1+m,cmp);
for(int i=1;i<=m;i++){
int fx=find(b[i].x),fy=find(b[i].y);
if(fx!=fy)
val[++res]=b[i].v,pre[fx]=res,pre[fy]=res,add(res,fx),add(res,fy);
if(res==n*2-1)
break;
}
}
int main(){
n=read(),m=read(),bin[1]=0;
for(int i=1;i<n*2;i++) pre[i]=i;
for(int i=1;i<=19;i++) bin[i]=bin[i-1]<<1;
for(int i=1;i<=m;i++) b[i].x=read(),b[i].y=read(),b[i].v=read();
build();
for(int i=1;i<=n;i++)
if(!vis[i])
dfs(find(i));
t=read();
while(t--){
int x=read(),y=read();
int p=lca(x,y);
// cout<<find(x)<<" "<<find(y)<<endl;
if(p==0)
cout<<"-1\n";
else
cout<<val[p]<<endl;
}
}