「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;
	}
}

posted @ 2019-02-13 19:36  撤云  阅读(321)  评论(0编辑  收藏  举报
……