今天拿了这道题目练练手,感觉自己代码能力又增强了不少;

我的思路跟别人可能不一样。

首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这个kruskal选边建图的过程。

 struct kruskalsolve{
int l,r,w;
}kr[maxm];
此处省略的内容接下来会有给出全部代码
int find(int x){
if(f[x] != x)f[x] = find(f[x]);
return f[x];
}
void kruskal_check(int m){
int cnte = ;
sort(kr+,kr+m+,cmp);
for(int i = ;i <= n;++i){
f[i] = i;
}
for(int i = ;i <= m;++i){
if(cnte == n-)break;
int s = find(kr[i].l);
int t = find(kr[i].r);
if(s != t){
f[s] = t;
e[++cnte][] = kr[i].l;
e[cnte][] = kr[i].r;
e[cnte][] = kr[i].w;
addedge(kr[i].l,kr[i].r);
addedge(kr[i].r,kr[i].l);
}
}
}

做到这里,有人可能觉得接下来一个LCA接着就可以AC了,不过蒟蒻认为这样做效率有点低,然后代码也不怎么好写,于是换成了树链剖分+线段树模板维护查询区间最大值的思路。(什么思路!!明明是套板子……这要解释的话就比较尴尬了)

这样的话效率就是O(nlogn)的总效率,感觉不错,但是就是代码量稍微有点大,请读者见谅。

建议大家还是先去学一下树链剖分的思路和板子,然后在看我的题解,毕竟光copy别人的,自己时间长了肯定忘,最好的还是自己懂了思路然后再自己手码出来。

废话不说了,上代码

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = ,maxm = ;
int n,m,q,s,t;
int id[maxn],top[maxn],son[maxn],fa[maxn],h[maxn],cnt,siz[maxn],dep[maxn],val[maxn],num,f[maxn];
struct kruskalsolve{
int l,r,w;
}kr[maxm];
struct edge{
int fr,to,next;
}edges[maxn<<];
struct segtree{
int l,r,val;
}tr[maxm<<];
int e[maxn][];
bool cmp(kruskalsolve a,kruskalsolve b){
return a.w < b.w;
}
void init(){
cnt = ;
memset(h,-,sizeof(h));
memset(dep,,sizeof(dep));
memset(siz,,sizeof(siz));
memset(fa,,sizeof(fa));
memset(id,,sizeof(id));
memset(edges,,sizeof(edge));
memset(val,,sizeof(val));
memset(e,,sizeof(e));
memset(top,,sizeof(top));
memset(tr,,sizeof(tr));
num = ;
}
void addedge(int u,int v){
edges[cnt].fr = u;edges[cnt].to = v;edges[cnt].next = h[u];
h[u] = cnt++;
}
int find(int x){
if(f[x] != x)f[x] = find(f[x]);
return f[x];
}
void kruskal_check(int m){
int cnte = ;
sort(kr+,kr+m+,cmp);
for(int i = ;i <= n;++i){
f[i] = i;
}
for(int i = ;i <= m;++i){
if(cnte == n-)break;
int s = find(kr[i].l);
int t = find(kr[i].r);
if(s != t){
f[s] = t;
e[++cnte][] = kr[i].l;
e[cnte][] = kr[i].r;
e[cnte][] = kr[i].w;
addedge(kr[i].l,kr[i].r);
addedge(kr[i].r,kr[i].l);
}
}
}
void dfs1(int now ,int father ,int d){
dep[now] = d;
fa[now] = father;
son[now] = ;
siz[now] = ;
for(int i = h[now];i != -;i = edges[i].next){
edge e1 = edges[i];
if(e1.to == father)continue;
dfs1(e1.to,now,d+);
siz[now] += siz[e1.to];
if(siz[son[now]] < siz[e1.to])son[now] = e1.to;
}
}
void getpos(int now,int tp){
id[now] = ++num;
top[now] = tp;
if(son[now])getpos(son[now],tp);
for(int i = h[now];i != -;i = edges[i].next){
edge e1 = edges[i];
if(e1.to == son[now] || e1.to == fa[now])continue;
getpos(e1.to,e1.to);
}
}
void push_up(int v){
tr[v].val = max(tr[v<<].val,tr[v<<|].val);
}
void build(int l,int r,int now){
tr[now].l = l;
tr[now].r = r;
if(l == r){
tr[now].val = val[l];
return;
}
int mid = (l + r) >> ;
build(l,mid,now<<);
build(mid+,r,now<<|);
push_up(now);
}
int query(int x,int l,int r){
if(l <= tr[x].l && r >= tr[x].r){
return tr[x].val;
}
int ans = ;
int mid = (tr[x].l + tr[x].r) >> ;
if(l <= mid)ans = max(ans,query(x<<,l,r));
if(r > mid)ans = max(ans,query(x<<|,l,r));
return ans;
}
int youth(int u,int v){
int ans = ;
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]])swap(u,v);
ans = max(ans,query(,id[top[u]],id[u]));
u = fa[top[u]];
}
if(u == v)return ans;
if(dep[u] > dep[v])swap(u,v);
ans = max(ans,query(,id[son[u]],id[v]));
return ans;
}
int main(){
init();
scanf("%d%d",&n,&m);
for(int i = ;i <= m;++i){
scanf("%d%d%d",&kr[i].l,&kr[i].r,&kr[i].w);
}
kruskal_check(m);
dfs1(,-,);
getpos(,);
for(int i = ;i < n;++i){
if(dep[e[i][]] < dep[e[i][]])swap(e[i][],e[i][]);
val[id[e[i][]]] = e[i][];
}
build(,n,);
scanf("%d",&q);
for(int i = ;i <= q;++i){
scanf("%d%d",&s,&t);
printf("%d\n",youth(s,t));
}
return ;
}

这次写的解题报告就到这里吧,以后会尽量去写。

习题:codevs 1519 过路费 解题报告的更多相关文章

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

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

  2. Codevs 1519 过路费(Mst+Lca)

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

  3. [Codevs1519]过路费解题报告|最小生成树|LCA

    在某个遥远的国家里,有 n个城市.编号为 1,2,3,…,n.这个国家的政府修建了m 条双向道路,每条道路连接着两个城市.政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值. ...

  4. codevs 1519 过路费

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

  5. 习题:codevs 2822 爱在心中 解题报告

    这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...

  6. 习题:codevs 1035 火车停留解题报告

    本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...

  7. 习题: codevs 2492 上帝造题的七分钟2 解题报告

    这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...

  8. [置顶] 刘汝佳《训练指南》动态规划::Beginner (25题)解题报告汇总

    本文出自   http://blog.csdn.net/shuangde800 刘汝佳<算法竞赛入门经典-训练指南>的动态规划部分的习题Beginner  打开 这个专题一共有25题,刷完 ...

  9. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

随机推荐

  1. atitit.Servlet2.5 Servlet 3.0 新特性 jsp2.0 jsp2.1 jsp2.2新特性

    atitit.Servlet2.5 Servlet 3.0 新特性 jsp2.0 jsp2.1 jsp2.2新特性   1.1. Servlet和JSP规范版本对应关系:1 1.2. Servlet2 ...

  2. Gitlab备份、升级、恢复

    一.备份 1.使用Omnibus安装包安装 --gitlab-rake gitlab:backup:create 2.使用源码安装 --./use_gitlab----如果备份失败,PATH路径错误, ...

  3. 在Windows系统搭建.NET Core环境并创建运行ASP.NET网站

    微软于6月27日在红帽DevNation峰会上 正式发布了.NET Core 1.0.ASP.NET 1.0和Entity Framework Core 1.0,其将全部支持Windows.OS X和 ...

  4. VMware虚拟机Mac OS X无法调整扩展硬盘大小,更新xcode时出现磁盘空间不足

    使用VMware虚拟机搭建的MacOSX,安装xcode时出现磁盘空间不足的错误. 因为很多朋友在初次安装MacOSX的时候都默认选择40G的磁盘大小,结果用了没两天之后就发现磁盘不够用了. 这时,百 ...

  5. Oracle Dataguard之Real-Time Apply

    Oracle Dataguard一共支持三种模式:最大可用模式(Maximum Availability),最大性能模式(Maximum Performance),最大保护模式(Maximum Pro ...

  6. Unity3D Player角色移动控制脚本

    1. 简介 在Unity3D中,有多种方式可以改变物体的坐标,实现移动的目的,其本质是每帧修改物体的position.之前写过类似的文章,这次增加了平时常用API的脚本,每个脚本均手打测试可用. 2. ...

  7. 优秀教程:使用 CSS3 动画实现的超炫的过渡特效

    Codrops 最近分享了一些很酷的图片切换灵感.有三种不同的用例:小的图像幻灯片,大标题幻灯片以及使用透明背景的产品幻灯片.状态转换使用 CSS 动画完成,我们能够定义从任何方向进来的图片的行为. ...

  8. SQL Server代理(6/12):作业里的工作流——深入作业步骤

    SQL Server代理是所有实时数据库的核心.代理有很多不明显的用法,因此系统的知识,对于开发人员还是DBA都是有用的.这系列文章会通俗介绍它的很多用法. 如我们在这里系列的前几篇文章所见,SQL ...

  9. vim黏贴自动增加tab的毛病

    vim在ctrl + p的时候有可能会自动给你增加了个tab 很是郁闷   解决方法如下: :set noautoindent :set nosmartindent

  10. 实现iOS图片等资源文件的热更新化(四): 一个最小化的补丁更新逻辑

    简介 以前写过一个补丁更新的文章,此处会做一个更精简的最小化实现,以便于集成.为了使逻辑具有通用性,将剥离对AFNetworking和ReativeCocoa的依赖.原来的文章,可以先看这里: htt ...