• 货车运输(洛谷P1967)——生成树+倍增LCA的一通乱搞


    题目原址在下面:

    题目大意:n个点m条边每次询问两点之间路径的最小值的最大值。

    思路:先跑一遍Kruskal,将边权从大到小排序,然后选n-1条边。之后跑倍增LCA。

    #include<bits/stdc++.h>
    using namespace std;
    const int P=30;
    struct nob{
    	int sta,ed,val,jump;
    }a[2000001],b[2000001];
    int n,m,num=0,f[1000001],tot=0,jump[1000001]={0},fa[1000001][30],root;
    int deep[1000001],qe,mina[1000001][30];
    bool judge[1000001]={0};
    bool mmp(nob a,nob b){
    	return a.val>b.val;
    }
    void add(int sta,int ed,int val){
    	num++;
    	a[num].sta=sta;
    	a[num].ed=ed;
    	a[num].val=val;
    }
    void ad(int sta,int ed,int val){
    	tot++;
    	b[tot].sta=sta;
    	b[tot].ed=ed;
    	b[tot].val=val;
    	b[tot].jump=jump[sta];
    	jump[sta]=tot;
    }
    int find(int x){
    	if (x==f[x]) return x;
    	f[x]=find(f[x]);
    	return f[x];
    }
    void dfs(int pos){
    	judge[pos]=true;
    	for (int i=jump[pos]; i; i=b[i].jump){
    		if (!judge[b[i].ed]){
    			fa[b[i].ed][0]=pos;
    			mina[b[i].ed][0]=b[i].val;
    			deep[b[i].ed]=deep[pos]+1;
    //			judge[a[i].ed]=1;
    			dfs(b[i].ed);
    		}
    	}
    }
    void bz(){
    	for (int i=1; i<P; i++){
    		for (int l=1; l<=n; l++){
    			fa[l][i]=fa[fa[l][i-1]][i-1];
    			mina[l][i]=min(mina[l][i-1],mina[fa[l][i-1]][i-1]);
    		}
    	}
    }
    int LCA(int x,int y){
    	int rem=1e9;
    	if (deep[x]<deep[y])
    	swap(x,y);
    	int d=deep[x]-deep[y];
    	for (int i=0; i<P; i++)
    		if ((1<<i)&d){
    			rem=min(rem,mina[x][i]);
    			x=fa[x][i];
    		}
    	if (x==y) return rem;
    	for (int i=P-1; i>=0; i--){
    		if (fa[x][i]!=fa[y][i]){
    			rem=min(rem,mina[x][i]);
    			rem=min(rem,mina[y][i]);
    			x=fa[x][i];
    			y=fa[y][i];
    		}
    	}
    	rem=min(rem,mina[x][0]);
    	rem=min(rem,mina[y][0]);
    	return rem;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1,x,y,val; i<=m; i++){
    		scanf("%d%d%d",&x,&y,&val);
    		add(x,y,val);
    		add(y,x,val);
    	}
    	sort(a+1,a+1+num,mmp);
    	for (int i=1; i<=n; i++)
    		f[i]=i;
    	for (int i=1; i<=num; i++){
    		if (find(a[i].sta)!=find(a[i].ed)){
    			f[find(a[i].sta)]=find(a[i].ed);
    			ad(a[i].sta,a[i].ed,a[i].val);
    			ad(a[i].ed,a[i].sta,a[i].val);
    		}
    	}
    	for (int i=1; i<=n; i++){
    		if (f[i]==i){
    			deep[i]=1;
    			judge[i]=true;
    			dfs(i);
    		}
    	}
    	bz();
    	scanf("%d",&qe);
    	for (int i=1,x,y; i<=qe; i++){
    		cin>>x>>y;
    		if (find(x)!=find(y)){
    			printf("-1
    ");
    			continue;
    		}
    		printf("%d
    ",LCA(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    钉钉小程序解析html的方法
    git使用
    electron-vue项目
    数组方法大全
    关于AJAX
    常用的东西
    常用正则表达式
    选项卡
    进度条
    泛型单列
  • 原文地址:https://www.cnblogs.com/cain-/p/7718679.html
Copyright © 2020-2023  润新知