#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define MAXN 10005
#define MAXM 100005 using namespace std; struct Edge { int from; int to; int val; int next; }; int n;
int m;
int q;
int cnt;
int num;
int f[MAXN];
int lv[MAXN];
int vis[MAXN];
int dis[MAXN];
int pre[MAXN];
int head[MAXN]; Edge s[MAXM],edge[MAXM]; inline bool cmp(Edge x,Edge y) { return x.val>y.val; } inline int find(int x)
{
if (f[x]!=x) return f[x]=find(f[x]);
return f[x];
} inline void add(int u,int v,int w)
{
edge[++cnt].from=u;
edge[cnt].to=v;
edge[cnt].val=w;
edge[cnt].next=head[u];
head[u]=cnt; return ;
} inline void dfs(int u)
{
for (int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if (!vis[v])
{
pre[v]=u; vis[v]=;
dis[v]=min(dis[v],edge[i].val);
lv[v]=lv[u]+; dfs(v);
}
} return ;
} inline int work(int x,int y)
{
int ans=;
while(lv[x]>lv[y]) ans=min(ans,dis[x]),x=pre[x];
while(lv[y]>lv[x]) ans=min(ans,dis[y]),y=pre[y];
while(x!=y) ans=min(ans,min(dis[x],dis[y])),x=pre[x],y=pre[y];
return ans;
} inline void solve()
{
scanf("%d%d",&n,&m); memset(dis,0x7f,sizeof(dis));
for (int i=;i<=n;i++) f[i]=i;
for (int i=;i<=m;i++)
scanf("%d%d%d",&s[i].from,&s[i].to,&s[i].val);
sort(s+,s++m,cmp); num=; cnt=;
for (int i=;i<=m&&num!=n-;i++)
{
int fa=find(s[i].from); int fb=find(s[i].to);
if (fa!=fb)
{
f[fa]=fb; num++;
add(s[i].from,s[i].to,s[i].val);
add(s[i].to,s[i].from,s[i].val);
}
} scanf("%d",&q); memset(vis,,sizeof(vis));
for (int i=;i<=n;i++)
if (!vis[i]) pre[i]=,lv[i]=vis[i]=,dfs(i);
for (int i=;i<=q;i++)
{
int a; int b; scanf("%d%d",&a,&b);
int fa=find(a); int fb=find(b);
if (fa!=fb) printf("-1\n");
else printf("%d\n",work(a,b));
} return ;
} int main()
{
solve();
return ;
}
废话我就不多说了 最初这道题写的是最大生成树加DFS搜索的 只能得到六十分 后来改成DFS的预处理 预处理的复杂度是O(n)的。
然后对于每一次询问 我这个算法的时间复杂度最坏是O(n)的。 也就是一棵树有两条链 询问的两个点分别是两条链底部的点。
不过数据显然没有这么水的  所以复杂度一般低于O(n)。 
说一说做法哈  先预处理所有的边 求出最大生成树 没有的话无所谓 只要所有的边扫一下 判边的话我用的是并查集维护 
把可以要的边留下就好 然后把这些边连起来
 对于每一个没有搜索过的点就去DFS搜一下 对于搜到的每一个节点要做一个等级标记 根节点等级是1 根节点的所有子节点等级是2 以此类推
DFS过程中记录一下每个点的前驱 以及每个点到它父亲的路径的权值 最后对于每一个询问AB两点
我用语言是不好说的 详情请看代码中的work代码 应该是非常容易理解的 嗯~ o(* ̄▽ ̄*)o 小编就先说到这里吧
如果看了有什么不懂的地方就在下面评论吧 小编会在12小时内给你满意的答复的 谢谢大家o(* ̄▽ ̄*)ブ

NOIP 2013 货车运输 最大生成树加DFS巧妙AC的更多相关文章

  1. NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】

    NOIP 2013 货车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在 ...

  2. [NOIp 2013]货车运输

    Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重 ...

  3. NOIP 2013货车运输

    当然这题有很多做法,但是我看到没有人写DSU的很惊奇 按照之前做连双向边题的经验,这题可以用并查集维护联通 然后对于每个询问\(x,y\),考虑启发式合并 当两个点集\(x,y\)合并时,一些涉及到其 ...

  4. NOIP提高组 2013货车运输

    觉得题目水的离开 不屑的大佬请离开 不会图论的请离开 ……. 感谢您贡献的访问量 ————————————华丽的分割线———————————— 题面: 题目描述 A 国有 n 座城市,编号从 1 到 ...

  5. 【NOIP】提高组2013 货车运输

    [算法]最大生成树+LCA(倍增) [题解]两点间选择一条路径最小值最大的路径,这条路径一定在最大生成树上,因为最大生成树就是从边权最大的边开始加的. 先求原图的最大生成树(森林),重新构图,然后用一 ...

  6. 题解 【luoguP1967 NOIp提高组2013 货车运输】

    题目链接 题解 题意 给你一个无向图,求两个点之间的一条路径,使路径上的最小值最大 算法:Kruskal最大生成树+倍增lca 分析 首先容易知道,答案一定在该图的最大生成树上 之后问题便转换成了树上 ...

  7. TZOJ 4848 货车运输(最大生成树+倍增lca)

    描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多 ...

  8. 【NOIP2013】货车运输 最大生成树+LCA

    题目描述 AA国有nn座城市,编号从 1到n,城市之间有m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重 ...

  9. $Noip2013/Luogu1967$ 货车运输 最大生成树+倍增$lca$

    $Luogu$ $Sol$ 首先当然是构建一棵最大生成树,然后对于一辆货车的起点和终点倍增跑$lca$更新答案就好.记得预处理倍增的时候不仅要处理走了$2^i$步后是那个点,还有这中间经过的路径权值的 ...

随机推荐

  1. Smokeping安装教程

    Smokeping安装教程 #Smokeping2.6.8安装教程 #2016.3.6 改编v1.0 #Linux运维技术交流 347163978   环境 CentOS release 6.4 (F ...

  2. android.graphic.Path

    类path是一个封装的几何学路径包括直线,二次曲线,三次曲线.它可以通过函数canvas.drawPath(path, paint)画出来,可以通过填充方式或者画线方式(由paint的style决定) ...

  3. SQL索引添加

    EXPLAIN select * from view_agzsaycommont  where id >0

  4. python引用py文件中文报错

    文件 a.py 中引用文件 b.py 如果文件b.py中包含中文,会报错. 文件hello.py中代码如下: def say_nihao(): print "你好" 文件main. ...

  5. New line

    The concepts of line feed (LF) and carriage return (CR) are closely associated, and can be either co ...

  6. Leetcode: Valid Word Square

    Given a sequence of words, check whether it forms a valid word square. A sequence of words forms a v ...

  7. 使用Visual Studio扩展插件Visual assist X给代码插入注释模板

    Visual Assist 是由Whole Tomato公司为Microsoft Visual Studio开发的一款插件.它对Visual Studio的智能提示功能和代码高亮功能进行了增强,同时还 ...

  8. web前端基础知识 jQuery

    通过之前的学习我们已经了解了html.css.javascript的相关知识:本次我们就共同学习进阶知识:jQuery~ 一.什么是jQuery? jQuery其实就是一个轻量级的javascript ...

  9. [转]彻底征服 Spring AOP 之 实战篇

    Spring AOP 实战 看了上面这么多的理论知识, 不知道大家有没有觉得枯燥哈. 不过不要急, 俗话说理论是实践的基础, 对 Spring AOP 有了基本的理论认识后, 我们来看一下下面几个具体 ...

  10. c++的引用

    /*#include"iostream"using namespace std;void any_function(int & p);//声明函数any_function/ ...