xsy 2018 【NOIP2013】货车运输
【NOIP2013】货车运输
Description
A 国有n座城市,编号从1到n,城市之间有m条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有q辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
Input
第一行有两个用一个空格隔开的整数n,m,表示A国有n座城市和m条道路。
接下来m行每行3个整数x,y,z,每两个整数之间用一个空格隔开,表示从x号城市到y号城市有一条限重为z的道路。注意:x不等于y,两座城市之间可能有多条道路。
接下来一行有一个整数q,表示有q辆货车需要运货。
接下来q行,每行两个整数x,y之间用一个空格隔开,表示一辆货车需要从x城市运输货物到y城市,注意:x不等于y。
接下来m行每行3个整数x,y,z,每两个整数之间用一个空格隔开,表示从x号城市到y号城市有一条限重为z的道路。注意:x不等于y,两座城市之间可能有多条道路。
接下来一行有一个整数q,表示有q辆货车需要运货。
接下来q行,每行两个整数x,y之间用一个空格隔开,表示一辆货车需要从x城市运输货物到y城市,注意:x不等于y。
Output
输出共有q行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出 −1。
Sample Input
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
Sample Output
3
-1
3
HINT
对于30%的数据,1≤n≤1000,1≤m≤10000,1≤q≤1000
对于60%的数据,1≤n≤1000,1≤m≤50000,1≤q≤1000
对于100%的数据,1≤n≤10000,1≤m≤50000,1≤q≤30000,0≤z≤100000
题解思路
首先,如果两点之间某路径上最小的一条边不在该图的最大生成树上,那么在这个图中,一定有一条路径,其中每一条边的值都大于等于那条边的值。
所以只需要求出最大生成树后再用LCA维护最小值即可。
时间复杂度:O(nlogn)
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; struct data{ int x,y,v; }t[50001],d[20001]; int n,m,s[10001][21],f[10001][21],fa[10001],h[10001],cnt,fx,fy,ans,p[10001],id[10001],x,y; bool cmp(data a,data b){ return a.v>b.v; } int father(int a){ if(fa[a]!=a)fa[a]=father(fa[a]); return fa[a]; } void add(int a,int b,int c){ cnt++; d[cnt].x=b; d[cnt].y=h[a]; d[cnt].v=c; h[a]=cnt; } void dfs(int a){ for(int i=1;i<=20;i++){ f[a][i]=f[f[a][i-1]][i-1]; s[a][i]=min(s[a][i-1],s[f[a][i-1]][i-1]); } for(int i=h[a];i;i=d[i].y){ if(!p[d[i].x]){ p[d[i].x]=p[a]+1; f[d[i].x][0]=a; s[d[i].x][0]=d[i].v; id[d[i].x]=id[a]; dfs(d[i].x); } } } void lca(int a,int b){ if(p[a]>p[b]){ for(int i=20;i>=0;i--){ if(p[f[a][i]]>=p[b]){ ans=min(ans,s[a][i]); a=f[a][i]; } } } if(p[a]<p[b]){ for(int i=20;i>=0;i--){ if(p[f[b][i]]>=p[a]){ ans=min(ans,s[b][i]); b=f[b][i]; } } } for(int i=20;i>=0;i--){ if(f[a][i]!=f[b][i]){ ans=min(ans,s[a][i]); ans=min(ans,s[b][i]); a=f[a][i]; b=f[b][i]; } } if(a!=b){ ans=min(ans,s[a][0]); ans=min(ans,s[b][0]); } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++)scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].v); for(int i=1;i<=n;i++)fa[i]=i; sort(t+1,t+m+1,cmp); for(int i=1;i<=m;i++){ fx=father(t[i].x); fy=father(t[i].y); if(fx!=fy){ fa[fx]=fy; add(t[i].x,t[i].y,t[i].v); add(t[i].y,t[i].x,t[i].v); } } for(int i=1;i<=n;i++){ if(!id[i]){ p[i]=1; id[i]=i; dfs(i); } } scanf("%d",&m); for(int i=1;i<=m;i++){ ans=10000000; scanf("%d%d",&x,&y); if(id[x]==id[y]){ lca(x,y); printf("%d\n",ans); }else printf("-1\n"); } }