[NOIP2013] 提高组 洛谷P1967 货车运输

题目描述

A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

输入输出格式

输入格式:

输入文件名为 truck.in。

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

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

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

接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。

输出格式:

输出文件名为 truck.out。

输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货

车不能到达目的地,输出-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%的数据,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,然后在两个结点到其最近公共祖先的路上找最短路,就是答案。

长度最小值也可以倍增求,但是一个个上溯好像也不会T

  1 /*by SilverN*/
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 using namespace std;
  8 const int mxn=300010;
  9 //bas
 10 int n,m;
 11 //edge
 12 struct li{
 13     int u,v,dis;
 14 }line[mxn];
 15 int cmp(li a,li b){
 16     return a.dis>b.dis;
 17 }
 18 struct node{
 19     int v,dis;
 20     int next;
 21 }e[mxn];
 22 int hd[mxn],cnt;
 23 //
 24 //bc
 25 int fa[mxn];
 26 void init(){
 27     for(int i=1;i<=n;i++)fa[i]=i;
 28 }
 29 int find(int x){
 30     if(fa[x]==x)return x;
 31     return fa[x]=find(fa[x]);
 32 }
 33 //tree
 34 int dep[mxn];
 35 int f[mxn][20];
 36 int w[mxn][20];
 37 //
 38 void add_edge(int u,int v,int dis){
 39     e[++cnt].next=hd[u];e[cnt].dis=dis;e[cnt].v=v;hd[u]=cnt;
 40     e[++cnt].next=hd[v];e[cnt].dis=dis;e[cnt].v=u;hd[v]=cnt;
 41 }
 42 void kruskal(){
 43     int i,j;
 44     int tot=1;
 45     for(i=1;i<=m;i++){
 46         int x=find(line[i].u),y=find(line[i].v);
 47         if(x!=y){
 48             fa[x]=y;
 49             tot++;
 50             add_edge(line[i].u,line[i].v,line[i].dis);
 51         }
 52     }
 53 }
 54 void dfs(int u,int fafa){
 55     dep[u]=dep[fafa]+1;
 56     f[u][0]=fafa;
 57     int i,j;
 58     for(i=hd[u];i;i=e[i].next){
 59         int v=e[i].v;
 60         if(v==fafa)continue;
 61         w[v][0]=e[i].dis;
 62         dfs(v,u);
 63     }
 64     return;
 65 }
 66 void solve(){
 67     int i,j;
 68     for(i=1;i<=n;i++)if(!dep[i]){
 69         dep[i]=1;
 70         dfs(i,0);
 71     }
 72     for(j=1;j<=18;j++)
 73       for(i=1;i<=n;i++){
 74           f[i][j]=f[f[i][j-1]][j-1];
 75       }
 76     for(j=1;j<=18;j++)
 77       for(i=1;i<=n;i++){
 78         w[i][j]=min(w[i][j-1],w[f[i][j-1]][j-1]);
 79       }
 80     
 81 }
 82 int LCA(int x,int y){
 83     if(dep[x]<dep[y])swap(x,y);
 84     int i;
 85     for(i=18;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];
 86     if(x==y)return x;
 87     for(i=18;i>=0;i--)
 88         if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
 89     return f[x][0];
 90 }
 91 int mdis(int x,int rt){
 92     int d=dep[x]-dep[rt];
 93     int res=1e9;
 94     for(int i=18;i>=0;i--)
 95         if((d>>i)&1){
 96             res=min(res,w[x][i]);
 97             x=f[x][i];
 98         }
 99     return res;
100 }
101 int main(){
102     scanf("%d%d",&n,&m);
103     int i,j;
104     int u,v,dis;
105     for(i=1;i<=m;i++) scanf("%d%d%d",&line[i].u,&line[i].v,&line[i].dis);
106     sort(line+1,line+m+1,cmp);
107     init();
108     kruskal();
109     solve();
110     int q;
111     scanf("%d",&q);
112     int x,y;
113     for(i=1;i<=q;i++){
114         scanf("%d%d",&x,&y);
115         if(find(x)!=find(y)){
116             printf("-1
");
117             continue;
118         }
119         int rt=LCA(x,y);
120         if(rt==0){
121             printf("-1
");
122             continue;
123         }
124         int ans=min(mdis(x,rt),mdis(y,rt));
125         printf("%d
",ans);
126     }
127     return 0;
128 }
原文地址:https://www.cnblogs.com/SilverNebula/p/5818702.html