[NOIp 2013]货车运输
Description
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
Input
输入文件名为 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 。
Output
输出文件名为 truck.out。
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货
车不能到达目的地,输出-1。
Sample Input
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
Sample Output
3
-1
3
Hint
对于 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。
题解
$Kruskal$+$LCA$+并查集
    建最大生成森林(以保证联通性的情况下最大化瓶颈路径)。
    并查集判断是否联通。
    若联通,$LCA$出路径上的最短边。
#include<map>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
#define RE register
#define IL inline
using namespace std;
const int N=;
const int M=; IL int Min(const int &a,const int &b) {return a<b ? a:b;} int n,m,q,lim,x,y;
struct tt
{
int from,to,cost;
}lin[M+];
IL bool comp(const tt &a,const tt &b) {return a.cost>b.cost;} int set[N+];
IL int Find(int r) {return set[r] ? set[r]=Find(set[r]):r;}
IL void Kruskal(); struct ss
{
int to,next,cost;
}edge[N*+];
int path[N+],top;
IL void Add(int u,int v,int c); bool vis[N+];
int fa[N+][],minn[N+][],dep[N+];
void Dfs(int r,int depth);
IL void RMQ(); IL int LCA(int x,int y); int main()
{
scanf("%d%d",&n,&m);lim=log2(n);
for (RE int i=;i<=m;i++) scanf("%d%d%d",&lin[i].from,&lin[i].to,&lin[i].cost);
Kruskal();
for (RE int i=;i<=n;i++) if (!vis[i]) Dfs(i,);
RMQ();
scanf("%d",&q);
while (q--)
{
scanf("%d%d",&x,&y);
int a=Find(x);
int b=Find(y);
if (a!=b) printf("-1\n");
else printf("%d\n",LCA(x,y));
}
return ;
} IL void Kruskal()
{
sort(lin+,lin+m+,comp);
int cnt=;
for (RE int i=;i<=m;i++)
{
int q=Find(lin[i].from);
int p=Find(lin[i].to);
if (p!=q)
{
set[p]=q;
cnt++;
Add(lin[i].from,lin[i].to,lin[i].cost);
Add(lin[i].to,lin[i].from,lin[i].cost);
if (cnt==n-) break;
}
}
}
IL void Add(int u,int v,int c)
{
edge[++top].to=v;
edge[top].next=path[u];
edge[top].cost=c;
path[u]=top;
}
void Dfs(int r,int depth)
{
vis[r]=;
dep[r]=depth;
for (RE int i=path[r];i;i=edge[i].next) if (!vis[edge[i].to])
{
fa[edge[i].to][]=r;
minn[edge[i].to][]=edge[i].cost;
Dfs(edge[i].to,depth+);
}
}
IL void RMQ()
{
for (RE int t=;t<=lim;t++)
for (RE int i=;i<=n;i++)
{
fa[i][t]=fa[fa[i][t-]][t-];
minn[i][t]=Min(minn[i][t-],minn[fa[i][t-]][t-]);
}
}
IL int LCA(int x,int y)
{
int ans=2e9;
if (dep[x]<dep[y]) swap(x,y);
for (RE int i=lim;i>=;i--) if (dep[x]-(<<i)>=dep[y])
{
ans=Min(ans,minn[x][i]);
x=fa[x][i];
}
if (x!=y)
{
for (RE int i=lim;i>=;i--) if (fa[x][i]!=fa[y][i])
{
ans=Min(ans,minn[x][i]);
ans=Min(ans,minn[y][i]);
x=fa[x][i];
y=fa[y][i];
}
ans=Min(ans,minn[x][]);
ans=Min(ans,minn[y][]);
x=fa[x][];
y=fa[y][];
}
return ans;
}
[NOIp 2013]货车运输的更多相关文章
- NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】
		
NOIP 2013 货车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在 ...
 - NOIP 2013 货车运输 最大生成树加DFS巧妙AC
		
#include<set> #include<map> #include<cmath> #include<queue> #include<stac ...
 - NOIP 2013货车运输
		
当然这题有很多做法,但是我看到没有人写DSU的很惊奇 按照之前做连双向边题的经验,这题可以用并查集维护联通 然后对于每个询问\(x,y\),考虑启发式合并 当两个点集\(x,y\)合并时,一些涉及到其 ...
 - NOIP提高组 2013货车运输
		
觉得题目水的离开 不屑的大佬请离开 不会图论的请离开 ……. 感谢您贡献的访问量 ————————————华丽的分割线———————————— 题面: 题目描述 A 国有 n 座城市,编号从 1 到 ...
 - 【NOIP】提高组2013 货车运输
		
[算法]最大生成树+LCA(倍增) [题解]两点间选择一条路径最小值最大的路径,这条路径一定在最大生成树上,因为最大生成树就是从边权最大的边开始加的. 先求原图的最大生成树(森林),重新构图,然后用一 ...
 - 题解 【luoguP1967 NOIp提高组2013 货车运输】
		
题目链接 题解 题意 给你一个无向图,求两个点之间的一条路径,使路径上的最小值最大 算法:Kruskal最大生成树+倍增lca 分析 首先容易知道,答案一定在该图的最大生成树上 之后问题便转换成了树上 ...
 - Codevs 3287 货车运输  2013年NOIP全国联赛提高组(带权LCA+并查集+最大生成树)
		
3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description A 国有 n 座 ...
 - [Noip 2013 Day1-3] 货车运输  做法总结
		
[Noip 2013 Day1-3] 货车运输 做法总结 Online Judge:Luogu-1967 Label:启发式合并,离线,整体二分,按秩合并,倍增,最大生成树 打模拟离线赛时做到,顺便总 ...
 - NOIP2013 货车运输 (最大生成树+树上倍增LCA)
		
死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...
 
随机推荐
- 200行Python代码实现2048
			
200行Python代码实现2048 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面 ...
 - 201421123042 《Java程序设计》第11周学习总结
			
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 1. 源代码阅读:多线程程序BounceThread 1.1 BallR ...
 - MSSQL 2000 错误823恢复
			
一.故障描述 MSSQL Server 2000 附加数据库错误823,附加数据库失败.数据库没有备份,不能通过备份恢复数据库,急需恢复数据库中的数据. 二.故障分析SQL Server数据库 823 ...
 - 解决java.lang.NoSuchMethodError:org.joda.time.DateTime.withTimeAtStartOfDay() Lorg/joda/time/DateTime
			
问题:项目放在weblogic运行,报错 java.lang.NoSuchMethodError: org.joda.time.DateTime.withTimeAtStartOfDay()Lorg/ ...
 - python构造一个freebuf新闻发送脚本
			
前言: 放假学习完web漏洞后.想写一个脚本 然而自己菜无法像大佬们一样写出牛逼的东西 尝试写了,都以失败告终. 还有一个原因:上学时间不能及时看到,自己也比较懒.邮件能提醒自己. 需要安装的模块: ...
 - Linq 等式运算符:SequenceEqual
			
检查元素的数量,每个元素的值及两个集合中元素的顺序是否相等,3个方面都相等则为true,否则为false IList<string> strList1 = new List<stri ...
 - GIT入门笔记(17)- 创建分支dev_lsq, 提交到代码
			
git服务器上默认的已经有主干和test分支. 开发人员提交代码流程如下: 1.用switch to->new branch创建dev1分支 2.push branch提交到dev1分支 3.在 ...
 - docker生态系统
			
我的docker学习笔记6-docker生态 1.镜像即应用 代码构建.持续集成和持续交付 DaoCloud.Quay.IO 2.催生容器托管caas服务 基 ...
 - 【第二十篇】C#微信H5支付 非微信内浏览器H5支付 浏览器微信支付
			
微信开发者文档 微信H5支付官方文档 请阅读清楚 最起码把所有参数看一遍 这个地方也可以看看 微信案例 http://wxpay.wxutil.com/mch/pay/h5.v2.php,请在微 ...
 - find文件查找
			
一.locate locate基于数据库索引来查找文件,数据库在开机时一段时间对更新,不会实时更新,数据库存放在(/var/lib/mlocate/mlocate.db),可以用updatedb来手动 ...