1519 过路费

时间限制: 1 s

空间限制: 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

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;

分类标签 Tags

分治 最小生成树 图论

/*
Slf(spfa优化).
50弃疗了.
跑最小生成树后Slf.
有一个链的测试点卡不过去.
(不搞mst的话还是能卡过去的).
论常数的重要性orz.
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define MAXN 100001
using namespace std;
int head[MAXN],n,m,k,cut,father[MAXN],tot,dis[MAXN],q[MAXN];
struct edge{int v,next;int x;}e[MAXN*2];
struct data{int x,y,z;}s[MAXN*2];
bool b[MAXN];
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x;
}
int ffind(int x)
{
return x!=father[x]?father[x]=ffind(father[x]):x;
}
void add(int u,int v,int z)
{
e[++cut].v=v;
e[cut].x=z;
e[cut].next=head[u];
head[u]=cut;
}
bool cmp(const data &x,const data &y)
{
return x.z<y.z;
}
int spfa(int s,int t)
{
int u,v;int head1=1,tail=1;
for(int i=1;i<=n;i++) dis[i]=1e10,b[i]=false;q[head1]=s;dis[s]=0;
while(head1<=tail)
{
u=q[head1++];b[u]=false;
if(head1>n+1) head1=1;
for(int i=head[u];i;i=e[i].next)
{
v=e[i].v;
if(dis[v]>max(dis[u],e[i].x))
{
dis[v]=max(dis[u],e[i].x);
if(!b[v])
{
b[v]=true;
if(dis[v]>dis[q[head1]])
{
if(--head1<0) head1=n;
q[head1]=v;
}
else {
q[++tail]=v;
if(tail>n+1) tail=1;
}
}
}
}
}
return dis[t];
}
int main()
{
int x,y,z;
n=read(),m=read();
for(int i=1;i<=n;i++) father[i]=i;
for(int i=1;i<=m;i++)
x=read(),y=read(),z=read(),s[i].x=x,s[i].y=y,s[i].z=z;
sort(s+1,s+m+1,cmp);
for(int i=1;i<=m;i++)
{
x=ffind(s[i].x),y=ffind(s[i].y);
if(x!=y){
tot++;
father[x]=y;
add(s[i].x,s[i].y,s[i].z);
add(s[i].y,s[i].x,s[i].z);
}
if(tot==n-1) break;
}
k=read();
while(k--)
{
x=read(),y=read();
printf("%d\n",spfa(x,y));
}
return 0;
}
/*
mst定理:最小生成树里的最长边最短.
然后lca维护两点距离.
还有不要漏下某种情况.
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define MAXN 100001
#define D 21
using namespace std;
int head[MAXN],n,m,k,cut,father[MAXN],tot,st,fa[MAXN][D+5],deep[MAXN],dis[MAXN][D+5];
struct edge{int v,next;int x;}e[MAXN*2];
struct data{int x,y,z;}s[MAXN*2];
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x;
}
int ffind(int x)
{
return x!=father[x]?father[x]=ffind(father[x]):x;
}
void add(int u,int v,int z)
{
e[++cut].v=v;
e[cut].x=z;
e[cut].next=head[u];
head[u]=cut;
}
bool cmp(const data &x,const data &y)
{
return x.z<y.z;
}
void dfs(int u,int f,int d)
{
deep[u]=d+1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if(f!=v){
fa[v][0]=u;
dis[v][0]=e[i].x;
dfs(v,u,d+1);
}
}
return ;
}
void get_father()
{
for(int j=1;j<=D;j++)
for(int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1],
dis[i][j]=max(dis[fa[i][j-1]][j-1],dis[i][j-1]);
return ;
}
int get_same(int u,int v)
{
for(int i=0;i<=D;i++)
{
if((1<<i)&v){
tot=max(tot,dis[u][i]);
u=fa[u][i];
}
}
return u;
}
int lca(int u,int v)
{
tot=0;
if(deep[v]>deep[u]) swap(u,v);
u=get_same(u,deep[u]-deep[v]);
if(u==v) return tot;
for(int i=D;i>=0;i--)
{
if(fa[u][i]!=fa[v][i])
{
tot=max(tot,max(dis[u][i],dis[v][i]));
u=fa[u][i];v=fa[v][i];
}
}
tot=max(tot,max(dis[u][0],dis[v][0]));
return tot;
}
int main()
{
int x,y,z;
n=read(),m=read();
for(int i=1;i<=n;i++) father[i]=i;
for(int i=1;i<=m;i++)
x=read(),y=read(),z=read(),s[i].x=x,s[i].y=y,s[i].z=z;
sort(s+1,s+m+1,cmp);
for(int i=1;i<=m;i++)
{
x=ffind(s[i].x),y=ffind(s[i].y);
if(x!=y){
tot++;
father[x]=y;
add(s[i].x,s[i].y,s[i].z);
add(s[i].y,s[i].x,s[i].z);
}
if(tot==n-1) break;
}
dfs(1,1,0);
get_father();
k=read();
while(k--)
{
x=read(),y=read();
printf("%d\n",lca(x,y));
}
return 0;
}

Codevs 1519 过路费(Mst+Lca)的更多相关文章

  1. codevs 1519 过路费 最小生成树+倍增

    /*codevs 1519 过路费 最小生成树+倍增*/ #include<iostream> #include<cstdio> #include<cstring> ...

  2. codevs 1519 过路费

    时间限制: 1 s  空间限制: 256000 KB  题目等级 : 大师 Master 题目描述 Description 在某个遥远的国家里,有 n个城市.编号为 1,2,3,…,n.这个国家的政府 ...

  3. 习题:codevs 1519 过路费 解题报告

    今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...

  4. codevs1519 过路费(最小生成树+LCA)

    1519 过路费  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 大师 Master     题目描述 Description 在某个遥远的国家里,有 n个城市.编号为 1,2 ...

  5. CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )

    CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...

  6. Codeforces 1108F MST Unification MST + LCA

    Codeforces 1108F MST + LCA F. MST Unification Description: You are given an undirected weighted conn ...

  7. GYM 101889I(mst+lca)

    最小生成树上倍增询问裸的. const int maxn = 2e5 + 5; int n, m, q; //图 struct Edge { int u, v; ll cost; bool opera ...

  8. [NOIP2013提高组] CODEVS 3287 火车运输(MST+LCA)

    一开始觉得是网络流..仔细一看应该是最短路,再看数据范围..呵呵不会写...这道题是最大生成树+最近公共祖先.第一次写..表示各种乱.. 因为要求运输货物质量最大,所以路径一定是在最大生成树上的.然后 ...

  9. CODEVS——T1519 过路费

    http://codevs.cn/problem/1519/ 时间限制: 1 s  空间限制: 256000 KB  题目等级 : 大师 Master 题解  查看运行结果     题目描述 Desc ...

随机推荐

  1. supersocket特征

    SuperSocket, 可扩展的 Socket 服务器框架 SuperSocket 是一个轻量级, 跨平台而且可扩展的 .Net/Mono Socket 服务器程序框架.你无须了解如何使用 Sock ...

  2. inline元素、block元素

    inline元素 不会独占一行,相邻的行内元素会排列在同一行内,直到一行排不下才会换行 高.行高.以及外边距和内边距不可改变 宽度就是它的文字或图片的宽度,不可改变,随元素内容变化而变化 内联元素只能 ...

  3. C#将字符串格式化为Json

    private string ConvertStringToJson(string str)        {            //格式化json字符串            JsonSeria ...

  4. A Pythonic Card Deck: __len__ & __getitem__ & for 循环的嵌套

    1. 列表生成式的嵌套 for 循环: 示例如下: li1 = range(1,6) li2 = list("ABC") # list("ABC") 的结果为 ...

  5. 转:git常用操作

    转自:https://www.cnblogs.com/donghaojun/p/10906981.html 开发常用git指令:git init  # 初始化本地git环境 git clone xxx ...

  6. day1-css练习[新浪首页顶部栏]

    直接贴代码吧: html代码 <div class="border-01"> <div class="border-001"> < ...

  7. vue-app物理返回键跳到指定页面

    例如提交订单成功跳到了订单详情页面,再返回就又到了提交订单支付页面 我们需要返回到其他页面 1.挂载完成后,判断浏览器是否支持popstate mounted(){ if (window.histor ...

  8. SpringBoot设置首页(默认页)跳转

    SpringBoot设置首页(默认页)跳转 方案1:controller里添加一个"/"的映射路径 @RequestMapping("/")public Str ...

  9. lumen时区

    今天用 Lumen 框架写代码时, 也是初次体验 Lumen, 遇到了一个问题, 从数据库里查出的时间比数据库里保存的 TIMESTAMP 时间慢了8个小时, 很明显这是一个时区设置的问题, 本以为可 ...

  10. 第十章、numpy模块

    目录 第十章.numpy模块 一.导入方式 二.作用 三.通过函数创建numpy数组 四. numpy数组运算 五.重点 第十章.numpy模块 一.导入方式 import numpy as np#约 ...