题目描述

Gremlins have infested the farm. These nasty, ugly fairy-like

creatures thwart the cows as each one walks from the barn (conveniently located at pasture_1) to the other fields, with cow_i traveling to from pasture_1 to pasture_i. Each gremlin is personalized and knows the quickest path that cow_i normally takes to pasture_i. Gremlin_i waits for cow_i in the middle of the final cowpath of the quickest route to pasture_i, hoping to harass cow_i.

Each of the cows, of course, wishes not to be harassed and thus chooses an at least slightly different route from pasture_1 (the barn) to pasture_i.

Compute the best time to traverse each of these new not-quite-quickest routes that enable each cow_i that avoid gremlin_i who is located on the final cowpath of the quickest route from pasture_1 to

pasture_i.

As usual, the M (2 <= M <= 200,000) cowpaths conveniently numbered 1..M are bidirectional and enable travel to all N (3 <= N <= 100,000) pastures conveniently numbered 1..N. Cowpath i connects pastures a_i (1 <= a_i <= N) and b_i (1 <= b_i <= N) and requires t_i (1 <= t_i <= 1,000) time to traverse. No two cowpaths connect the same two pastures, and no path connects a pasture to itself (a_i != b_i). Best of all, the shortest path regularly taken by cow_i from pasture_1 to pasture_i is unique in all the test data supplied to your program.

By way of example, consider these pastures, cowpaths, and [times]:

1--[2]--2-------+
| | |
[2] [1] [3]
| | |
+-------3--[4]--4
TRAVEL     BEST ROUTE   BEST TIME   LAST PATH
p_1 to p_2 1->2 2 1->2
p_1 to p_3 1->3 2 1->3
p_1 to p_4 1->2->4 5 2->4

When gremlins are present:

TRAVEL     BEST ROUTE   BEST TIME    AVOID
p_1 to p_2 1->3->2 3 1->2
p_1 to p_3 1->2->3 3 1->3
p_1 to p_4 1->3->4 6 2->4

For 20% of the test data, N <= 200.

For 50% of the test data, N <= 3000.

TIME LIMIT: 3 Seconds

MEMORY LIMIT: 64 MB

Gremlins最近在农场上泛滥,它们经常会阻止牛们从农庄(牛棚_1)走到别的牛棚(牛_i的目的 地是牛棚_i).每一个gremlin只认识牛_i并且知道牛_i一般走到牛棚_i的最短路经.所以它 们在牛_i到牛棚_i之前的最后一条牛路上等牛_i. 当然,牛不愿意遇到Gremlins,所以准备找 一条稍微不同的路经从牛棚_1走到牛棚_i.所以,请你为每一头牛_i找出避免gremlin_i的最 短路经的长度.

和以往一样, 农场上的M (2 <= M <= 200,000)条双向牛路编号为1..M并且能让所有牛到 达它们的目的地, N(3 <= N <= 100,000)个编号为1..N的牛棚.牛路i连接牛棚a_i (1 <= a_i <= N)和b_i (1 <= b_i <= N)并且需要时间t_i (1 <=t_i <= 1,000)通过. 没有两条牛路连接同样的牛棚,所有牛路满足a_i!=b_i.在所有数据中,牛_i使用的牛棚_1到牛 棚_i的最短路经是唯一的.

输入输出格式

输入格式:

* Line 1: Two space-separated integers: N and M

* Lines 2..M+1: Three space-separated integers: a_i, b_i, and t_i

输出格式:

* Lines 1..N-1: Line i contains the smallest time required to travel from pasture_1 to pasture_i+1 while avoiding the final cowpath of the shortest path from pasture_1 to pasture_i+1. If no such path exists from pasture_1 to pasture_i+1, output -1 alone on the line.

输入输出样例

输入样例#1:

4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输出样例#1:

3
3
6 提交地址 : Luogu2934 题意:
给你一些点, 他们与节点1的最短路的最后一条边不可走, 求每一个点到1的最短距离; 这道题很折磨人...
首先我们考虑一颗最短路径树(就是1到每个节点的最短路径路过的边构成的集合);

然后我们要找一个点对(x, y),且xy之间有边,xy不在最短路径树上,y在节点i的子树里,x不在节点i的子树里;

这样,我们要找的节点i的"非最短路径",就是dis(x) + dis(y) - dis(i) + w(x, y);
其中, dis代表节点到根节点的最短路径, w(x, y)代表x 到 y 的路径长度; 我们发现 : dis(i) 是确定的, 所以我们要最小化dis(x) + dis(y) + w(x, y); 我们可以用左偏树维护(才不会写) 想学戳这里 我直接排序; 选出不在最短路径树上的边, 按dis(x) + dis(y) + w(x, y)最小sort一遍; 然后更新答案; 我们接着想 : 一个点如果已经被更新, 那么一定是最优的, 为什么, 因为他的dis值确定, 而我们已经对以上那一坨式子的值按由小到大排序,所以我们第一次更新一定是他的最优值;
所以我们可以用并查集维护, 确保他们只被更新一次; 那么我们再想 : 一个点对(x, y),能更新那些点的ans呢?
能更新到x -> LCA(x, y) 和 y -> LCA(x, Y) 的所有点;
为什么?
因为 边 x-y 一定不是点i的父亲边 (题面说了), 如果我们更新到LCA(x, y) 那么x, y就在同一个子树里了;
而我们能更新i的前提是x, y不在同一子树里;
所以我们就像跳LCA一样一直往上跳, 一路更新答案, 然后修改并查集, 直到调到LCA; 应该比较好懂; 卡SPFA?差评!! 代码奉上:
//By zZhBr
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#include <queue>
using namespace std;
const int N = ;
const int M = ; inline int read()
{
int res = ;
bool flag = ;
char c = getchar();
while (c < '' or c > '')
{
if (c == '-') flag = ;
c = getchar();
}
while (c >= '' and c <= '')
{
res = res * + c - '';
c = getchar();
}
return flag ? -res : res;
} int n, m;
int A[M], B[M], C[M];
int what[M];//第几条边属于的编号 what[i] = what[i^1];
int is[M]; //记录最短路径中第i个点的入边
bool itis[M];//记录是否是最短路径树的树边
int fafa[N];//记录在最短路径树中一个节点的父亲
int fa[N];//并查集
int ans[N];//记录答案 inline int Find(int x)
{
return x == fa[x] ? x : fa[x] = Find(fa[x]);
} struct edge
{
int nxt;
int to;
int val;
}ed[M]; int head[N], cnt; inline void add(int x, int y, int z, int gg)
{
cnt++;
ed[cnt].nxt = head[x];
ed[cnt].to = y;
ed[cnt].val = z;
head[x] = cnt;
what[cnt] = gg;
} inline void add(int x, int y)
{
cnt++;
ed[cnt].nxt = head[x];
ed[cnt].to = y;
head[x] = cnt;
} struct date
{
int x;
int y;
int w;
// date(){}
// date(int xx, int yy, int ww){x = xx, y = yy, w = ww;}
}cf[M]; bool cmp(date a, date b)
{
return a.w < b.w;
} void dfs(int x) //简陋的寻找父亲的函数
{
for (register int i = head[x] ;i ; i = ed[i].nxt)
{
int to = ed[i].to;
if (to == fafa[x]) continue;
fafa[to] = x;
dfs(to);
}
} /*.............................Dijkstra...................................*/
struct dij{int x, w;}; bool operator <(const dij &a,const dij &b)
{
return a.w > b.w;
} int dis[N];
bool vis[N]; inline void Dijkstra(int haha)
{
memset(dis, 0x3f, sizeof dis); priority_queue < dij > q; dis[haha] = ;
q.push((dij){haha, }); while (!q.empty())
{
dij t = q.top(); q.pop();
int x = t.x;
if (vis[x]) continue;
vis[x] = ;
for (register int i = head[x] ; i ; i = ed[i].nxt)
{
int to = ed[i].to;
if (!vis[to] and dis[to] > dis[x] + ed[i].val) //!
{
is[to] = what[i];
dis[to] = dis[x] + ed[i].val;
q.push((dij){to, dis[to]});
}
}
}
}
/*.................................End..............................................*/ int main()
{
n = read(), m = read(); for (register int i = ; i <= m ; i ++)
{
A[i] = read(), B[i] = read(), C[i] = read();
add(A[i], B[i], C[i], i);
add(B[i], A[i], C[i], i);
} Dijkstra(); cnt = ;
memset(head, , sizeof head); // for (int i=2;i<=n;i++)cout<<is[i]<<endl; for (register int i = ; i <= n ; i ++)
{
int x = is[i];
add(A[x], B[x]);
add(B[x], A[x]);
itis[x] = ;
} dfs(); int num = ;
for (register int i = ; i <= m ; i ++) //该搞非树边了
{
if (itis[i]) continue;
// printf("%d\n", i);
cf[++num] = (date) {A[i], B[i], dis[A[i]] + dis[B[i]] + C[i]};
} sort (cf + , cf + + num, cmp); for (register int i = ; i <= n ; i ++) fa[i] = i, ans[i] = -; for (register int i = ; i <= num ; i ++)
{
int x = cf[i].x, y = cf[i].y;
x = Find(x), y = Find(y); //printf("x = %d, y = %d\n", x, y);
while (x != y)
{
if (dis[x] < dis[y]) swap(x, y);
ans[x] = cf[i].w - dis[x];
fa[x] = fafa[x];
x = Find(x);
} } for (register int i = ; i <= n ; i ++)
{
printf("%d\n", ans[i]);
}
return ; } zZhBr

 

可以转载, 但请注明地址谢谢;


[USACO09JAN]安全出行Safe Travel 最短路,并查集的更多相关文章

  1. luogu P2934 [USACO09JAN]安全出行Safe Travel

    题目链接 luogu P2934 [USACO09JAN]安全出行Safe Travel 题解 对于不在最短路树上的边(x, y) 1 | | t / \ / \ x-----y 考虑这样一种形态的图 ...

  2. P2934 [USACO09JAN]安全出行Safe Travel

    P2934 [USACO09JAN]安全出行Safe Travel https://www.luogu.org/problemnew/show/P2934 分析: 建出最短路树,然后考虑一条非树边u, ...

  3. 洛谷—— P2934 [USACO09JAN]安全出行Safe Travel || COGS ——279|| BZOJ——1576

    https://www.luogu.org/problem/show?pid=2934 题目描述 Gremlins have infested the farm. These nasty, ugly ...

  4. ●洛谷P2934 [USACO09JAN]安全出行Safe Travel

    题链: https://www.luogu.org/problemnew/show/P2934 题解: 最短路(树),可并堆(左偏堆),并查集. 个人感觉很好的一个题. 由于题目已经明确说明:从1点到 ...

  5. 【BZOJ1576】[Usaco2009 Jan]安全路经Travel 最短路+并查集

    [BZOJ1576][Usaco2009 Jan]安全路经Travel Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, ...

  6. BZOJ1576: [Usaco2009 Jan]安全路经Travel(最短路 并查集)

    题意 给你一张无向图,保证从1号点到每个点的最短路唯一.对于每个点求出删掉号点到它的最短路上的最后一条边(就是这条路径上与他自己相连的那条边)后1号点到它的最短路的长度 Sol emmm,考场上想了个 ...

  7. 「BZOJ1576」[Usaco2009 Jan] 安全路经Travel------------------------P2934 [USACO09JAN]安全出行Safe Travel

    原题地址 题目描述 Gremlins have infested the farm. These nasty, ugly fairy-like creatures thwart the cows as ...

  8. [USACO09JAN]安全出行Safe Travel

    题目 什么神仙题啊,我怎么只会\(dsu\)啊 我们考虑一个非常暴力的操作,我们利用\(dsu\ on \ tree\)把一棵子树内部的非树边都搞出来,用一个堆来存储 我们从堆顶开始暴力所有的边,如果 ...

  9. WOJ#2423 安全出行Safe Travel

    描述 精灵最近在农场上泛滥,它们经常会阻止牛们从农庄(牛棚_1)走到别的牛棚(牛_i的目的 地是牛棚_i).每一个精灵只认识牛_i并且知道牛_i一般走到牛棚_i的最短路经.所以它们在牛_i到牛棚_i之 ...

随机推荐

  1. 关于spring boot多张表建立外健的讨论

    现在有四张表:student(学生表).blogs(博客表).comment(评论表).reply(回复表) 现在说一下这四张表: student(学生表):学生的信息记录表 blogs(博客表):学 ...

  2. 《即时消息技术剖析与实战》学习笔记7——IM系统的消息未读

    一.什么是消息未读 消息未读包括会话未读和总未读.前者指的是当前用户和某一聊天方的未读消息数,后者指的是当前用户的所有未读消息数,也就是所有会话未读的和.比如用户A收到用户B的2条消息,还收到用户C的 ...

  3. thinkphp6.0 集成Alipay 手机和电脑端支付的方法

    本文由 BI8EJM 原创,转载请注明出处! 第一步 下载 Alipay 的PHP SDK  :https://docs.open.alipay.com/54/103419/ 第二步 解压下载都到的压 ...

  4. 为什么使用B+Tree索引?

    什么是索引? 索引是一种数据结构,具体表现在查找算法上. 索引目的 提高查询效率 [类比字典和借书] 如果要查"mysql"这个单词,我们肯定需要定位到m字母,然后从下往下找到y字 ...

  5. .netCore+Vue 搭建的简捷开发框架

    话不多说,上图: 整体项目结构如图所示,我的设计初衷是基于.netCore + DI + Vue 打造一个适合初学者的简捷开发框架. 架构模型采用基于RESTful API风格的前后台分离框架,总体分 ...

  6. 快速开始使用spark

    1.版本说明 在spark2.0版本以前,spakr编程接口是RDD(Resilient Distributed Dataset,弹性分布式数据集),spark2.0版本即以上,RDD被Dataset ...

  7. SQL Server 内存优化表的索引设计

    测试的版本:SQL Server 2017 内存优化表上可以创建哈希索引(Hash Index)和内存优化非聚集(NONCLUSTERED)索引,这两种类型的索引也是内存优化的,称作内存优化索引,和基 ...

  8. windows安装Mycat并测试

    1.下载系统安装包 选择相应的版本进行下载,地址:http://dl.mycat.io/ .Mycat数据库分库分表中间件介绍 http://www.mycat.io/ 2.安装 安装mycat前需要 ...

  9. Java 学习笔记之 Daemon线程

    Daemon线程: 线程: 用户线程 守护线程 守护线程是一种特殊的线程,在进程中不存在非守护线程了,则守护线程自动销毁. public class DaemonThread extends Thre ...

  10. Eclipse导入别人项目爆红叉

    1.导入项目之前,请确认工作空间编码已设置为utf-8:window->Preferences->General->Wrokspace->Text file encoding- ...