NOIP2013 货车运输
3.货车运输
(truck.cpp/c/pas)
【问题描述】
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。
【输入输出样例】
|
truck.in |
truck.out |
||||
|
4 |
3 |
3 |
|||
|
1 |
2 |
4 |
-1 |
||
|
2 |
3 |
3 |
3 |
||
|
3 |
1 |
1 |
|||
|
3 |
|||||
|
1 |
3 |
||||
|
1 |
4 |
||||
|
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。
【思路】
MST+LCA
可以知道如果运最大重量的货物,货车所走的一定是最大生成树上的边。
方法:kruskal求解最大生成树。
对于每个询问uv,找到两者的最近公共祖先r,那么货车走过的路线就是u->r->v,所以只需要在寻找LCA的时候比较路上的最小边即可。
方法:暴力。先将uv挪到相同深度上来,然后并行向上寻找公共祖先。
注意:当uv不属于同一个树中的时候意味着两者不互通,需要提前判断。
【代码】
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<(c);a++)
using namespace std; const int maxn = +, maxm=+;
int n,m;
int father[maxn]; //并查集
struct Edge{
int u,v,d;
bool operator <(const Edge& rhs) const{ //最大生成树
return d>rhs.d;
}
};
struct Edge2{
int v,d,next;
};
inline int find(int u) {
return u==father[u]? u:father[u]=find(father[u]);
}
struct LCA{
int first[maxm]; //链表式存初图
Edge2 e[maxm]; int en; int dist[maxn][maxn]; //[][]
int d[maxn]; //深度数组
int p[maxn]; //p数组记录父节点
int root; void init() {
en=; root=n/; //root的选取会影响时间
for(int i=;i<n;i++) first[i]=-;
d[]=;
}
void AddEdge(int u,int v,int d){
++en;
e[en].v=v; e[en].d=d;
e[en].next=first[u];
first[u]=en;
}
void build_tree(int u,int fa) { //have failed
//根据MST得出的初图(edges)建树->depth[] parent[] dist[][]
//无根树->有根树
for(int i=first[u];i>;i=e[i].next) { //i=next[i]!!!
int v=e[i].v;
if(v!=fa) {
d[v]=d[u]+; dist[u][v]=dist[v][u]=e[i].d;
build_tree(v,p[v]=u); //v!=fa
}
}
}
void Move(int& u,int depth,int &ans){ //u溯回到高度为depth的祖先的位置
while(d[u]!=depth) { ans=min(ans,dist[u][p[u]]); u=p[u]; }
}
int query(int u,int v) {
if(find(u) != find(v)) return -; //uv之间不可达
int ans=<<;
if(d[u]<d[v]) Move(v,d[u],ans); else if(d[u]>d[v]) Move(u,d[v],ans);
while(u != v) {
ans=min( ans , min(dist[u][p[u]],dist[v][p[v]]) );
u=p[u]; v=p[v];
}
return ans;
}
};
LCA lca;
struct Kruskal{
vector<Edge> edges; void init() {
edges.clear();
for(int i=;i<n;i++) father[i]=i;
}
void AddEdge(int u,int v,int d) {
edges.push_back((Edge){u,v,d});
}
void MST() {
lca.init();
sort(edges.begin(),edges.end());
int cnt=;
int nc=edges.size();
for(int i=;i<nc;i++) {
int u=edges[i].u,v=edges[i].v,d=edges[i].d;
int x=find(u),y=find(v);
if(x!=y) {
lca.AddEdge(u,v,d); //利用MST中的边构造lca
lca.AddEdge(v,u,d); //反向边
father[x]=y;
if(++cnt==n-) return ; //判断有n-1条边提前结束
}
}
}
}; Kruskal krus; int main() {
ios::sync_with_stdio(false);
cin>>n>>m;
krus.init();
FOR(i,,m) { //uv 0..
int u,v,d;
cin>>u>>v>>d; u--; v--;
krus.AddEdge(u,v,d);
}
krus.MST();
lca.build_tree(lca.root,-);
int q; cin>>q;
FOR(i,,q) {
int u,v; cin>>u>>v; u--; v--;
cout<<lca.query(u,v)<<"\n";
}
return ;
}
NOIP2013 货车运输的更多相关文章
- [Luogu 1967] NOIP2013 货车运输
[Luogu 1967] NOIP2013 货车运输 一年多前令我十分头大的老题终于可以随手切掉了- 然而我这码风又变毒瘤了,我也很绝望. 看着一年前不带类不加空格不空行的清纯码风啊,时光也好像回去了 ...
- NOIP2013 货车运输(最大生成树,倍增)
NOIP2013 货车运输(最大生成树,倍增) A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道 ...
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...
- Codevs3278[NOIP2013]货车运输
3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description A 国有 ...
- 【洛谷P1967】[NOIP2013]货车运输
货车运输 题目链接 显然,从一点走到另一点的路径中,最小值最大的路径一定在它的最大生成树上 所以要先求出最大生成树,再在生成树上找最近公共祖先,同时求出最小值. #include<iostrea ...
- noip2013货车运输
P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过 ...
- NOIP2013货车运输[lca&&kruskal]
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...
- [noip2013]货车运输(kruskal + 树上倍增)
描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多 ...
- [luogu P1967][NOIp2013] 货车运输
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...
随机推荐
- 贪心算法——将正整数变为1
题目链接http://toutiao.com/a6320936270101528833/ 为避免链接失效,再粘贴一下题目内容: 给你一个数n,有3种操作: 1.这个数加1 2.这个数减1 3.如果这个 ...
- LocalStorage 本地存储
首先自然是检测浏览器是否支持本地存储.在HTML5中,本地存储是一个window的属性,包括localStorage和sessionStorage,从名字应该可以很清楚的辨认二者的区别,前者是一直存在 ...
- Deadline来了,如何按时结题?
- uva 624
背包问题 总时间为容量,单个唱片时间为各个物体的价值与体积 f[] 用来记录路径 #include <cstdio> #include <cstring> #define ...
- PHP 7 值得期待的新特性(下)
这是我们期待已久的 PHP 7 系列文章的第二篇.点此阅读 第一篇本文系 OneAPM 工程师编译整理. 也许你已经知道,重头戏 PHP 7 的发布将在今年到来!现在,让我们来了解一下,新版本有哪些新 ...
- poj 2454 Jersey Politics 随机化
随机化算法+贪心! 将3*k排序后分成3分,将第二第三份的和分别加起来,让和与500*k比较,都大于则输出,否则,随机生成2个数,在第二第三份中交换! 代码如下: #include<iostre ...
- 李洪强iOS开发本人集成环信的经验总结_09_处理好友请求
李洪强iOS开发本人集成环信的经验总结_09_处理好友请求 实现这种效果: 01 - 遵守处理好友请求的代理协议 02 - 设置代理 03 - 实现代理方法 04 - 实现代理中用到的方法
- Silverlight之OOB模式下的一些事
本文简介: 1.为什么要使用OOB?使用OOB的作用? 2.如何实现OOB模式 3.对OOB进行一些设置: 4.检测OOB的安装状态: 5.更新应用程序: 6.WebBrowser控件: 7.桌面通知 ...
- python函数--传参
一.位置参数 二.关键字参数 三.默认参数 四.任意数量的位置参数: 1. *x 2. 传入的多个参数,最终合并成一个元组 3. 之后的参数必须用关键字参数 五.任意数量的关键字参数 1. **x 2 ...
- ~/.ctag的作用与配置
里边可以有基本配置和语言正则表达式解析的参数 # Basic options --recurse=yes --tag-relative=yes --exclude=.git # Regex for C ...