描述
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入
第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
输出
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。
样例输入
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
样例输出
3
-1
3
提示
对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q < 1,000;
对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q < 1,000;
对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q < 30,000,0 ≤ z ≤ 100,000。
题意
如上
题解
要使路径上的最小值尽可能大,跑一个最大生成树
然后在查询树上路径最小值的时候,可以跑一个倍增lca
查询u,v的最小值的时候,先找到u,v的公共祖先p,再求min(up的最小值,vp的最小值)
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=10005; 5 const int maxm=50005; 6 int deep[maxn],fa[maxn][20],dis[maxn][20],lg[maxn],vis[maxn],f[maxn],n,m; 7 vector< pair<int,int> >G[maxn]; 8 struct edge 9 { 10 int u,v,w; 11 bool operator<(const edge &D)const{ 12 return w>D.w; 13 } 14 }edges[maxm]; 15 void dfs(int u) 16 { 17 vis[u]=1; 18 for(auto X:G[u]) 19 { 20 int v=X.first; 21 int w=X.second; 22 if(vis[v])continue; 23 fa[v][0]=u; 24 dis[v][0]=w; 25 deep[v]=deep[u]+1; 26 dfs(v); 27 } 28 } 29 void RNQ() 30 { 31 for(int j=1;(1<<j)<=n;j++) 32 for(int i=1;i<=n;i++) 33 fa[i][j]=fa[fa[i][j-1]][j-1], 34 dis[i][j]=min(dis[i][j-1],dis[fa[i][j-1]][j-1]); 35 } 36 int lca(int x,int y) 37 { 38 if(deep[x]<deep[y])swap(x,y); 39 while(deep[x]>deep[y])x=fa[x][lg[deep[x]-deep[y]]-1]; 40 if(x==y)return x; 41 for(int k=lg[deep[x]];k>=0;k--) 42 if(fa[x][k]!=fa[y][k]) 43 x=fa[x][k],y=fa[y][k]; 44 return fa[x][0]; 45 } 46 int find(int x) 47 { 48 return f[x]==x?x:f[x]=find(f[x]); 49 } 50 int query(int x,int y) 51 { 52 int ans=0x3f3f3f3f,t=deep[x]-deep[y]; 53 for(int i=0;i<=16;i++) 54 if(t&(1<<i)) 55 ans=min(ans,dis[x][i]), 56 x=fa[x][i]; 57 return ans; 58 } 59 void max_kruskal() 60 { 61 int cnt=0; 62 sort(edges,edges+m); 63 for(int i=0;i<m;i++) 64 { 65 int u=edges[i].u; 66 int v=edges[i].v; 67 int w=edges[i].w; 68 int fu=find(u); 69 int fv=find(v); 70 if(fu!=fv) 71 { 72 G[u].push_back({v,w}); 73 G[v].push_back({u,w}); 74 f[fu]=fv; 75 if(++cnt==n-1)break; 76 } 77 } 78 } 79 int main() 80 { 81 memset(dis,0x3f3f3f3f,sizeof dis); 82 memset(vis,false,sizeof vis); 83 int u,v,w,q; 84 scanf("%d%d",&n,&m); 85 for(int i=1;i<=n;i++)lg[i]=lg[i-1]+(1<<lg[i-1]==i),f[i]=i; 86 for(int i=0;i<m;i++) 87 { 88 scanf("%d%d%d",&u,&v,&w); 89 edges[i]={u,v,w}; 90 } 91 max_kruskal(); 92 for(int i=1;i<=n;i++)if(!vis[i])dfs(i); 93 RNQ(); 94 scanf("%d",&q); 95 for(int i=0;i<q;i++) 96 { 97 scanf("%d%d",&u,&v); 98 if(find(u)!=find(v))printf("-1 "); 99 else 100 { 101 int father=lca(u,v); 102 printf("%d ",min(query(u,father),query(v,father))); 103 } 104 } 105 return 0; 106 }