codevs1519过路费
来源:互联网 发布:听音乐下载什么软件 编辑:程序博客网 时间:2024/04/28 09:25
题目描述 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 2 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;
分析:
这个题目的话,注意到“政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值。”这一句就可以很容易的想到这可以用最小生成树来解,然后求最小值的话,可用倍增来求lca就可以了,具体细节的话看代码
代码
#include <cstdio>#include <algorithm>#include <iostream>using namespace std;struct edge{ int u,v,w; bool operator < (const edge &h)const{ return w < h.w; }}a[102000];int fa[12000];int rn[12000][15];int rp[12000][15];int he[12000];int ne[22000];int to[22000];int we[22000];int de[12000];int n,m;int rea();int fin(int);void uni(int,int);void dfs(int,int);int lca(int,int);int main(){ n=rea() , m = rea(); for(int i=1;i<=n;++i) fa[i] = i; for(int i=1;i<=m;++i) a[i].u=rea() , a[i].v=rea() , a[i].w=rea(); sort(a+1,a+m+1); for(int i=1,k=1,p,q;i<=m&&k<n;++i){ p = fin(a[i].u); q = fin(a[i].v); if(p != q){ fa[p] = q; k++; ne[k]=he[a[i].u];he[a[i].u]=k;to[k]=a[i].v;we[k]=a[i].w; ne[k+n]=he[a[i].v];he[a[i].v]=k+n;to[k+n]=a[i].u;we[k+n]=a[i].w; } } de[1] = 1; dfs(1,-1); int q = rea(); for(int i=1;i<=q;++i) printf("%d\n",lca(rea(),rea())); return 0;}int rea(){ int in = 0; char ch = getchar(); while(ch>'9' || ch<'0') ch = getchar(); while(ch>='0' && ch<='9'){ in = in*10+ch-'0'; ch = getchar(); } return in;}int fin(int x){ int r = x; while(r != fa[r]) r = fa[r]; int p; while(x != fa[x]){ p = fa[x]; fa[x] = r; x = p; } return r;}void uni(int x,int y){ fa[fin(x)] = fin(y);}void dfs(int x,int y){ for(int i=he[x];i;i=ne[i]) if(to[i] != y){ rn[to[i]][0] = x; rp[to[i]][0] = we[i]; de[to[i]] = de[x]+1; for(int j=1;rn[rn[to[i]][j-1]][j-1];++j){ rn[to[i]][j] = rn[rn[to[i]][j-1]][j-1]; rp[to[i]][j] = max(rp[to[i]][j-1],rp[rn[to[i]][j-1]][j-1]); } dfs(to[i],x); }}int lca(int x,int y){ int ans = 0; if(de[x] > de[y]) swap(x,y); int derta = de[y]-de[x]; for(int i=0;(1<<i)<=derta;++i) if(derta&(1<<i)){ ans = max(ans,rp[y][i]); y = rn[y][i]; } if(x == y) return ans; for(int i=0;;++i) if(rn[x][i] == rn[y][i]){ if(i == 0) return max(ans,max(rp[x][0],rp[y][0])); else{ ans = max(ans,max(rp[x][i-1],rp[y][i-1])); x = rn[x][i-1]; y = rn[y][i-1]; i = -1; } }}
0 0
- codevs1519过路费
- 【codevs1519】过路费 mst+lca
- CodeVS1519 过路费【Kruskal+倍增求LCA】
- 过路费
- 过路费
- FOJ2082 过路费
- 过路费 FZU
- codevs 过路费
- FZU2082-过路费
- FZU Problem 2082 过路费
- zoj 2082 过路费
- 【树链剖分】 FZU 2082 过路费
- fzu 2082 过路费(树链剖分)
- fzu2082 过路费 树链剖分
- FZU 2082 过路费 (树链剖分)
- FZU 2082 过路费 树链剖分
- codevs 1519 过路费
- FZU - 2082 过路费(树剖)
- LTE-TDD HARQ(1)-上行HARQ时序
- redis安装,命令详解,配置详解,java客户端如何使用,都在这里
- 限制对比度自适应直方图均衡化算法原理、实现及效果
- UVA 437_The Tower of Babylon
- UnityEditor下文件操作方法汇总(Unity3D开发之二十四)
- codevs1519过路费
- node之classnames模块
- 通用分页工具类
- 珍藏多年的素材,灵感搜寻网站
- 博客抽了
- 如何写一份“耐看”的商业计划书?
- USACO1.1:ride
- Android 原生导航 I-ActionBar
- iOS开发-进阶:通过(lame)将录制音频转换成Mp3