额呵呵,找到一个照片开始乱搞ing。(嘻嘻

car-driver

  • 前奏
  • 题目大意
  • 题目解法
    • 最小生成树
    • LCA

前奏

让我们进入正题,这道题目所涉知识面是很广的。
先来列举一下这道题的知识点:最小生成树(最好是克鲁斯卡尔,也就是说我们还要用到并查集)+LCA(最好是倍增的)+(链式前向星)
*其实我们这道题要应用的是最大生成树,但是其实和最小生成树差异不大,所以在后文我还是叫最小生成树。

所以对上面知识有问题的同学,建议去看一下以下文章:

最小生成树详细解析

链式前向星

倍增求LCA

LCA连我自己都还没找到比较好的博客,所以,有时间自己复习梳理的时候写一篇。


题目大意

给出你一幅图和一些边,每条边有一些权值,两两城市间会有不止一条边
问你从x城市到y城市的所有可行的路径方案中,最小边的最大值是多少
若两城市不连通则输出-1

对于 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。


题目解法

因为数据比较大,所以我们这题不讲部分分。
因为直接暴力不是0分就是玄学水到20。
两个步骤,最小生成树+LCA(最近公共祖先)

最小生成树

相对于prim,克鲁斯卡尔会快一点。所以我们选择性能优异的后者,而后者的思想主要是这样的:
先排序,找到从小到大的权值的边的序列。(因为是最大生成树,所以这里是从大到小。
而我们要一个个去处理这些边,如果这些边的起始点和终点并不连接的话,我们就要保留这条边,所以在这里我们要用到并查集。我们可以将进行合并操作,使得这棵树的边数最好缩小到节点数-1,而联通所有的节点。

if(find(a[i].u)!=find(a[i].v))fa[find(a[i].u)]=find(a[i].v)

并且,我们在这里可以用到链式前向星存边了。可以比矩阵快一点。

add(a[i].u,a[i].v,a[i].dis)

LCA

我们知道,这样建出来的树一定是可以求出符合题意答案的树,所以我们直接考虑找答案。
为了让我们的答案不让别的因素影响。
举个例子,如果多走了一条边,这条边的边权比我们的答案要大,其实对我们的答案没有影响,因为我们要选的答案是路径上权值最小的一条边。
如果这条边的权值比我们的答案要小,其实对我们的答案还有不利影响。

这里讲倍增的方法;
先预处理出每个节点的2的幂次祖先,然后在 O ( l o g ( n ) ) O(log(n)) O(log(n))的时间复杂度上求出路径的极值。然后,我们就要用到一个很重要的式子,它的用处是转移F数组的值:
f [ x ] [ i ] = f [ f [ x ] [ i − 1 ] ] [ i − 1 ] ; f[x][i]=f[f[x][i-1]][i-1]; f[x][i]=f[f[x][i−1]][i−1];
然后,为了符合题意,我们就要求LCA中的最小值。
在倍增的方法中,我们需要选择一种“跳”的方法,将两个数的点跳到同一层,这样可以使得我们求的LCA就是他们上一层的节点。
然后,我们还需要用到一个数组来记录一下就好了。

#include<bits/stdc++.h>
using namespace std;
int n,m,q,x,y;
int fa[10005];
int next[20005],first[20005],go[20005],dis[20005],tot;
int dep[10005],f[10005][30],fm[10005][30];
struct node{int u,v,dis;
}a[50005];
int read()
{int f=1,x=0;char s=getchar();while(s<'0'||s>'9'){if(s=='-') f=-1;s=getchar();}while(s>='0'&&s<='9') x=x*10+s-'0',s=getchar();return x*f;
}
void qsort(int l,int r)
{int i=l,j=r,mid=a[(l+r)/2].dis;while(i<=j){while(a[i].dis>mid) i++;while(a[j].dis<mid) j--;if(i<=j) swap(a[i],a[j]),i++,j--;}if(l<j) qsort(l,j);if(i<r) qsort(i,r);
}
void add(int u,int v,int len)//链式前向星
{next[++tot]=first[u];first[u]=tot;go[tot]=v,dis[tot]=len;next[++tot]=first[v];first[v]=tot;go[tot]=u,dis[tot]=len;
}
int find(int x)
{if(fa[x]==x) return x;return fa[x]=find(fa[x]);
}
void ready(int o,int from)
{dep[o]=dep[from]+1;for(int i=1;i<=20;i++){f[o][i]=f[f[o][i-1]][i-1];fm[o][i]=min(fm[f[o][i-1]][i-1],fm[o][i-1]);}for(int i=first[o];i;i=next[i]){int v=go[i];if(v==from)continue;fm[v][0]=dis[i];f[v][0]=o;ready(v,o);}
}
int lca(int x,int y)
{int minx=0x7fffffff;if(dep[y]>dep[x]) swap(x,y);for(int i=20;i>=0;i--){if(dep[f[x][i]]>=dep[y]){minx=min(minx,fm[x][i]);x=f[x][i];}if(x==y) return minx; }for(int i=20;i>=0;i--){if(f[x][i]!=f[y][i]){minx=min(minx,min(fm[x][i],fm[y][i]));x=f[x][i];y=f[y][i];}}return min(minx,min(fm[x][0],fm[y][0]));
}
int main()
{n=read(),m=read();for(int i=1;i<=n;++i) fa[i]=i;for(int i=1;i<=m;++i) a[i].u=read(),a[i].v=read(),a[i].dis=read();qsort(1,m);for(int i=1;i<=m;++i)if(find(a[i].u)!=find(a[i].v))fa[find(a[i].u)]=find(a[i].v),add(a[i].u,a[i].v,a[i].dis);ready(1,0);q=read();for(int i=1;i<=q;++i){x=read(),y=read();if(find(x)!=find(y)) printf("-1\n"); else printf("%d\n",lca(x,y));}return 0;
}

【NOIP2013提高组day1】货车运输相关推荐

  1. 【NOIP2013提高组】火柴排队

    题目背景 NOIP2013 提高组 Day1 试题 题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定 ...

  2. NOIP2013 提高组复赛解题报告

    NOIP2013 提高组复赛 day1 day\;1 1002. 火柴排队 贪心+数据结构/归并排序 这个"相邻交换"让我联想到了NOIP2012_day1_task2_game那 ...

  3. 【题解】P1979 [NOIP2013 提高组] 华容道(SPFA,BFS,常数优化)

    [题解]P1979 [NOIP2013 提高组] 华容道 最近打比赛次次挂..平均每周得被至少一场比赛打击一次(这周好不容易 ABC 打的还行模拟赛又挂--)心烦意乱.写篇题解疏散一下内心的苦闷(雾) ...

  4. 【NOIP2013提高组】花匠

    题目背景 NOIP2013 提高组 Day2 试题. 题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空 ...

  5. P1979 [NOIP2013 提高组] 华容道

    题目来源 [NOIP2013 提高组] 华容道 - 洛谷 题目考点 搜索   图论 题目 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, ...

  6. 【NOIP2013提高组】积木大赛

    题目背景 NOIP2013 提高组 Day2 试题 题目描述 春春幼儿园举办了一年一度的"积木大赛".今年比赛的内容是搭建一座宽度为 n 的大厦,大厦可以看成由 n 块宽度为 1  ...

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

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

  8. 【杂题总汇】NOIP2013(洛谷P1967) 货车运输

    [洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...

  9. 【NOIP2013提高组T3】加分二叉树

    题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都 ...

最新文章

  1. 微软大神“玩”出新花样,求平均值代码还能这样写?
  2. mp4转gif_mp4转gif怎么转?一键转码的技巧要知道
  3. ABAP类的继承、多态、重载
  4. 用JS解决多行溢出文本的省略问题
  5. POJ-3352-RoadConstruction(边双联通分量,缩点)
  6. idea html ajax,在 IntelliJ IDEA 8.1中编写一个ajax jquery实例,取不到页面上的值
  7. 【Flink】Flink 系统监控指标
  8. KeyMob--移动广告聚合平台界的黑马
  9. 小程序中里的bindinput_云开发实战分享|诗和远方:旅行小账本云开发
  10. “留得五湖明月在,不愁无处下金钩“太经典,分享一下
  11. TCP/IP协议之常见的应用层协议——DNS域名系统
  12. Two-Stream Convolutional Networksfor Action Recognition in Videos——学习笔记
  13. SEO是什么意思?为什么要做SEO?
  14. 中小团队如何快速制定推送运营体系
  15. 简单魔兽改键的基本原理及基于MFC实现
  16. kafka使用教程、快速上手
  17. MATLAB运动目标检测系统
  18. 目前微型计算机的一般容量是,目前微型计算机的内存容量一般是( )。
  19. 华中科技大学计算机学院辅导员,计算机学院辅导员寒假走访学生家庭
  20. 蒲公英 Ghost Win 7 Sp1(x86/x64)旗舰版 2018 08

热门文章

  1. c++中“箭头(-)”和“点号(.)”操作符的区别
  2. day01 Redis
  3. 企业如何搭建并运营好积分商城?
  4. web前端人员每天必须关注的前端社区网站
  5. 波卡的盔甲与弱肋 |链捕手
  6. 算法优化:旋转对称图最优解法及思路分享(几乎最优)
  7. linux startx无效_startx启动图形界面失败的几个解决方法
  8. 用Python打造属于自己的“今日头条” | 一个非常适合练手的全栈项目
  9. 基于Qt的ui图形化界面进行的界面设计
  10. 关于AppInventor之gzjkw.net版本的电脑模拟器用法