【洛谷】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 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。
如果货车不能到达目的地,输出 -1−1。
输入输出样例
输入 #1
4 3 1 2 4 2 3 3 3 1 1 3 1 3 1 4 1 3
输出 #1
3 -1 3
说明/提示
对于 30% 的数据,1≤n<1000,1≤m<10,000,1≤q<1000;
对于 60% 的数据,1≤n<1000,1≤m<5×10^4,1≤q<1000;
对于 100% 的数据,1≤n<10^4,1≤m<5×10^4,1≤q<3×10^4,0≤z≤10^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)); } }

浙公网安备 33010602011771号