【洛谷】P1967 货车运输(kruskal+LCA)

题目描述

A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。

现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

输入格式

第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。

接下来 m 行每行三个整数 x,y,z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。
注意: x≠y,两座城市之间可能有多条道路 。

接下来一行有一个整数 q,表示有 q 辆货车需要运货。

接下来 q 行,每行两个整数 x,y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,保证 x≠y

输出格式

共有 qq 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。
如果货车不能到达目的地,输出 -11。

输入输出样例

输入 #1
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
输出 #1
3
-1
3

说明/提示

对于 30% 的数据,1n<1000,1m<10,000,1q<1000;

对于 60% 的数据,1n<1000,1m<5×10^4,1q<1000;

对于 100% 的数据,1n<10^4,1m<5×10^4,1q<3×10^4,0z10^5。


最小(大)生成树+LCA

#include<iostream>
#include<sstream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#include<algorithm>
#define INF 0X3f3f3f3f
using namespace std;
int N,last[100001]={0},f[100001]={0},dep[100001]={0},wealth[100001][55]={0},F[100001][55]={0},vis[100001]={0};
struct Node{
    int x,y,z;
}A[100001];
struct node{
    int to,edge,next;
}a[100001];
inline int add(int UU,int VV,int VAL){
    a[++N].to=VV;
    a[N].edge=VAL;
    a[N].next=last[UU];
    last[UU]=N;
    return 0;
}
inline int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1,ch=getchar();}
    while('0'<=ch&&ch<='9'){s=s*10+ch-'0',ch=getchar();}
    return s*w;
}
int cmp(Node XXX,Node YYY){
    return XXX.z>YYY.z;
}
int dad(int X){
    if(f[X]==X) return X;
    return f[X]=dad(f[X]);
}
int dfs(int me,int father){
    vis[me]=1;
    dep[me]=dep[father]+1;
    F[me][0]=father;
    for(int i=last[me];i;i=a[i].next){
        if(vis[a[i].to]==1) continue;
        wealth[a[i].to][0]=a[i].edge;
        dfs(a[i].to,me);
    }
    return 0;
}
int Min(int XX,int YY){
    if(XX>YY) return YY;
    return XX;
}
int LCA(int l,int r){
    int ans=INF;
    if(dad(l)!=dad(r)) return -1;
    if(dep[r]>dep[l]) swap(l,r);
    for(int i=20;i>=0;i--)
        if(dep[F[l][i]]>=dep[r]){
            ans=Min(ans,wealth[l][i]);
            l=F[l][i];
        }
    if(l==r) return ans;
    for(int i=20;i>=0;i--)
        if(F[l][i]!=F[r][i]){
            ans=Min(ans,Min(wealth[l][i],wealth[r][i]));
            l=F[l][i];
            r=F[r][i];
        }
    ans=Min(ans,Min(wealth[l][0],wealth[r][0]));
    return ans;
}
int main(){
    //freopen("33.in","r",stdin);
    memset(wealth,INF,sizeof(wealth));
    int n=read(),m=read();
    for(int i=1;i<=m;i++) A[i].x=read(),A[i].y=read(),A[i].z=read();
    sort(A+1,A+m+1,cmp);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++){//最小生成树
        int zx1=dad(A[i].x),zx2=dad(A[i].y);
        if(zx1==zx2) continue;
        f[zx1]=zx2;
        add(A[i].x,A[i].y,A[i].z);
        add(A[i].y,A[i].x,A[i].z);
    }
    for(int i=1;i<=n;i++){
        if(vis[i]==1) continue;
        dfs(i,0);
    }
    for(int i=1;i<=20;i++)
        for(int j=1;j<=n;j++){
            F[j][i]=F[F[j][i-1]][i-1];
            wealth[j][i]=Min(wealth[j][i-1],wealth[F[j][i-1]][i-1]);
        }
    int Q=read();
    while(Q--){
        int L,R;
        L=read(),R=read();
        printf("%d\n",LCA(L,R));
    }
}

 

posted @ 2020-08-21 16:24  latent_Lin  阅读(108)  评论(0)    收藏  举报