CODEVS——T1519 过路费

 空间限制: 256000 KB
 题目等级 : 大师 Master
 
 
题目描述 Description

    在某个遥远的国家里,有 n个城市。编号为 1,2,3,…,n。这个国家的政府修建了m 条双向道路,每条道路连接着两个城市。政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值。如:A到B长度为 2,B到C 长度为3,那么开车从 A经过 B到C 需要上交的过路费为 3。
    佳佳是个做生意的人,需要经常开车从任意一个城市到另外一个城市,因此他需要频繁地上交过路费,由于忙于做生意,所以他无时间来寻找交过路费最低的行驶路线。然而, 当他交的过路费越多他的心情就变得越糟糕。 作为秘书的你,需要每次根据老板的起止城市,提供给他从开始城市到达目的城市,最少需要上交多少过路费。

输入描述 Input Description

    第一行是两个整数 n 和m,分别表示城市的个数以及道路的条数。 
    接下来 m 行,每行包含三个整数 a,b,w(1≤a,b≤n,0≤w≤10^9),表示a与b之间有一条长度为 w的道路。
    接着有一行为一个整数 q,表示佳佳发出的询问个数。 
    再接下来 q行,每一行包含两个整数 S,T(1≤S,T≤n,S≠T), 表示开始城市S 和目的城市T。

输出描述 Output Description

    输出共q行,每行一个整数,分别表示每个询问需要上交的最少过路费用。输入数据保证所有的城市都是连通的。

样例输入 Sample Input

4 5 
1 2 10 
1 3 20 
1 4 100 
2 4 30 
3 4 10 

1 4 
4 1

样例输出 Sample Output

20 
20

数据范围及提示 Data Size & Hint

对于 30%的数据,满足 1≤ n≤1000,1≤m≤10000,1≤q≤100; 
对于 50%的数据,满足 1≤ n≤10000,1≤m≤10000,1≤q≤10000; 
对于 100%的数据,满足 1≤ n≤10000,1≤m≤100000,1≤q≤10000;

(和货车运输很像)

先求出最小生成树(使图简化),在此树上做倍增,维护最大代价

 1 #include <algorithm>
 2 #include <cstring>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 
 7 const int N(10000+15);
 8 const int M(100000+5);
 9 int n,m,q,u,v,ans;
10 struct Edge
11 {
12     int u,v,w;
13 }road[M];
14 bool cmp(Edge a,Edge b)
15 {
16     return a.w<b.w;
17 }
18 
19 int head[N],sumedge;
20 struct E
21 {
22     int v,next,w;
23     E(int v=0,int next=0,int w=0):
24         v(v),next(next),w(w){}
25 }edge[N<<1];
26 void ins(int u,int v,int w)
27 {
28     edge[++sumedge]=E(v,head[u],w);
29     head[u]=sumedge;
30 }
31 
32 int fa[N];
33 int find(int x)
34 {
35     return x==fa[x]?x:fa[x]=find(fa[x]);
36 }
37 void K()
38 {
39     int cnt=0;
40     sort(road+1,road+m+1,cmp);
41     for(int i=1;i<=n;i++) fa[i]=i;
42     for(int i=1;i<=m;i++)
43     {
44         int x=road[i].u,y=road[i].v;
45         int fx=find(x),fy=find(y);
46         if(fx==fy) continue;
47         fa[fx]=fy;
48         ins(x,y,road[i].w);
49         ins(y,x,road[i].w);
50         if(++cnt==n-1) return ;
51     }
52 }
53 
54 int dad[N],val[N],deep[N];
55 void DFS(int x)
56 {
57     deep[x]=deep[dad[x]]+1;
58     for(int i=head[x];i;i=edge[i].next)
59     {
60         int v=edge[i].v;
61         if(dad[v]) continue;
62         val[v]=edge[i].w;
63         dad[v]=x;  DFS(v);
64     }
65 }
66 int LCA(int x,int y)
67 {
68     int maxx=0,maxn=0;
69     if(deep[x]>deep[y]) swap(x,y);
70     for(;deep[y]>deep[x];y=dad[y]) maxx=max(maxx,val[y]);
71     for(;x!=y;x=dad[x],y=dad[y]) maxn=max(maxn,max(val[x],val[y]));
72     return max(maxn,maxx);
73 }
74 
75 int main()
76 {
77     scanf("%d%d",&n,&m);
78     for(int i=1;i<=m;i++)
79         scanf("%d%d%d",&road[i].u,&road[i].v,&road[i].w);
80     K(); DFS(1);
81     scanf("%d",&q);
82     for(;q--;)
83     {
84         scanf("%d%d",&u,&v);
85         printf("%d
",LCA(u,v));
86     }
87     return 0;
88 }
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
原文地址:https://www.cnblogs.com/Shy-key/p/7308057.html