题链:

https://www.luogu.org/problemnew/show/P2934

题解:

最短路(树),可并堆(左偏堆),并查集。

个人感觉很好的一个题。
由于题目已经明确说明:从1点到每个点的最短路有且只有一条。
那么跑完最短路后,就可以得到一个最短路树,即每个点只有一个来源点。

然后来考虑,如果某一个u点无法从其最短路树上的father到达时,是个怎样的情况:

由于u无法从其父亲到达,所以如果还存在1到u的路径的话,

应该在其子树内(包括u),存在一个v点,与子树外的某个节点x通过一条x和v之间的非树边,

形成这样一个从1到u的新最短路:1 → x →  v → u,

特别的,不能出现x是u的父亲且v就是u点的情况。(因为那条边已经被玩坏了2333)

那么这样的话,新的1到u的距离就是$dis[x]+e[x→v]+dis[v]-dis[u]$。

令$W(x,v)=dis[x]+e[x→v]+dis[v]$

因为要新的距离最小,所以就应该找到一对合法的(x,v)使得$W(x,v)$最小。


那么为什么答案就一定这种形式1 → x →  v → u的呢?

为何不能是1 → x → y → v → u,或者经过更多的子树外的节点呢?

(图中的虚线表示最短路树上的路径)

如果经过了两个子树外的节点,那么距离d1就是:

$d1=dis[x]+e1+e2+dis[v]-dis[u]$

如果只经过了一个子树外的节点,比如是y,那么距离d2就是:

$d2=dis[y]+e2+dis[v]-dis[u]$

如果d2>d1的话,即按照之前的疑问,如果经过两个子树外节点会使得答案比经过一个子树外节点优,

那么:

$d2-d1>0$

$dis[y]+e2+dis[v]-dis[u]-(dis[x]+e1+e2+dis[v]-dis[u])>0$

$dis[y]-dis[x]-e1>0$

$dis[y]>dis[x]+e1$,与dis[y]是1到y的最短路矛盾,所以最优答案一定是只经过一个子树外节点

(经过更多的子树外节点的情况可以自己试着证明一下。)


那么现在就需要对每个节点u,维护出对其合法的最小的W(x,v),那么答案ANS[u]=W(x,v)-dis[u]。

而这个W(x,v)的维护就直接使用小根堆即可完成,

为了保证时间复杂度,我们需要从树下往上依次处理每个点的答案,

会涉及到把u节点的众多儿子v的堆合并,所以要用到可并堆(本人使用的是左偏堆)。

同时合并后,可能有些在堆里的W(x,v)就不合法了,因为有的x,v处在了同一个子树内,

但是不需要直接在堆里去删除,只用维护一个并查集,在取堆顶时判断该W(x,v)是否合法即可。

代码:

#include<bits/stdc++.h>
#define MAXN 100050
using namespace std;
int N,M;
int pre[MAXN],dis[MAXN],ANS[MAXN],order[MAXN];
struct Info{
int x,y,w;
bool operator < (const Info &rtm) const{
return w<rtm.w;
}
};
struct Edge{
int ent;
int to[MAXN*4],nxt[MAXN*4],val[MAXN*4],head[MAXN];
Edge(){ent=2;}
void Adde(int u,int v,int w){
to[ent]=v; val[ent]=w;
nxt[ent]=head[u]; head[u]=ent++;
}
}E;
struct UFSet{
int fa[MAXN];
void Reset(int n){
for(int i=1;i<=n;i++) fa[i]=i;
}
int Findfa(int u){
if(u==fa[u]) return u;
else return fa[u]=Findfa(fa[u]);
}
void Union(int x,int y){
static int fx,fy;
fx=Findfa(x); fy=Findfa(y);
if(fx==fy) return; fa[fx]=fy;
}
bool Insame(int x,int y){
return Findfa(x)==Findfa(y);
}
}S;
struct LT{
//Define the LEN of the leaf is 1.
int dnt;
Info d[MAXN*4];
int root[MAXN],ls[MAXN*4],rs[MAXN*4],len[MAXN*4];
int Merge(int u,int v){
if(!u||!v) return u+v;
if(d[v]<d[u]) swap(u,v);
rs[u]=Merge(rs[u],v);
if(len[ls[u]]<len[rs[u]]) swap(ls[u],rs[u]);
len[u]=len[rs[u]]+1;
return u;
}
void Insert(int u,Info now){//Insert a new node into the heap of u
++dnt; d[dnt]=now,len[dnt]=1;//As a new node, it's a leaf.
root[u]=Merge(root[u],dnt);
}
int Pop(int u){
return Merge(ls[u],rs[u]);
}
Info Top(int u){
static Info ret;
while(ret=d[root[u]],ret.x&&S.Insame(ret.x,ret.y)){
// cout<<"Delete : "<<ret.x<<" < - > "<<ret.y<<" : "<<ret.w<<endl;
root[u]=Pop(root[u]);
}
return ret;
}
}H;
void Dijkstra(){
typedef pair<int,int>Pii; int ont=0;
priority_queue<Pii,vector<Pii>,greater<Pii> >Q;
memset(dis,0x3f,sizeof(dis));
Q.push(make_pair(dis[1]=0,1));
while(!Q.empty()){
Pii now=Q.top(); Q.pop();
int u=now.second;
if(now.first>dis[u]) continue;
order[++ont]=u;
for(int e=E.head[u];e;e=E.nxt[e]){
int v=E.to[e];
if(dis[v]<=dis[u]+E.val[e]) continue;
dis[v]=dis[u]+E.val[e]; pre[v]=u;
Q.push(make_pair(dis[v],v));
}
}
}
int main(){
scanf("%d%d",&N,&M);
for(int i=1,a,b,c;i<=M;i++)
scanf("%d%d%d",&a,&b,&c),
E.Adde(a,b,c),E.Adde(b,a,c);
Dijkstra(); S.Reset(N);
for(int i=N;i>=1;i--){
int u=order[i];
for(int e=E.head[u];e;e=E.nxt[e]){
int v=E.to[e];
if(v==pre[u]||S.Insame(u,v)) continue;
H.Insert(u,(Info){u,v,dis[u]+dis[v]+E.val[e]});
}
Info now=H.Top(u);
if(!now.x) ANS[u]=-1;
else ANS[u]=now.w-dis[u];
H.root[pre[u]]=H.Merge(H.root[pre[u]],H.root[u]);
S.Union(pre[u],u);
}
for(int i=2;i<=N;i++) printf("%d\n",ANS[i]);
return 0;
}

  

●洛谷P2934 [USACO09JAN]安全出行Safe Travel的更多相关文章

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

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

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

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

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

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

  4. [USACO09JAN]安全出行Safe Travel 最短路,并查集

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

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

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

  6. [USACO09JAN]安全出行Safe Travel

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

  7. 洛谷——P2935 [USACO09JAN]最好的地方Best Spot

    P2935 [USACO09JAN]最好的地方Best Spot 题目描述 Bessie, always wishing to optimize her life, has realized that ...

  8. 2018.07.06 洛谷P2936 [USACO09JAN]全流Total Flow(最大流)

    P2936 [USACO09JAN]全流Total Flow 题目描述 Farmer John always wants his cows to have enough water and thus ...

  9. 洛谷 P2935 [USACO09JAN]最好的地方Best Spot

    题目描述 Bessie, always wishing to optimize her life, has realized that she really enjoys visiting F (1 ...

随机推荐

  1. 第十一条:谨慎的覆盖clone()方法

    一个类要想实现克隆,需要实现Cloneable接口,表明这个类的对象具有克隆的功能. Cloneable接口是一个mixin接口,它里面并没有任何的抽象方法,类似的接口有Serializable接口, ...

  2. 201621123043 《Java程序设计》第7周学习总结

    1. 本周学习总结 2.书面作业 1. GUI中的事件处理 1.1 写出事件处理模型中最重要的几个关键词. 事件:用户的操作. 事件源:产生事件的组件. 事件监听程序:对事件进行处理的操作所引发的相关 ...

  3. NetFPGA-1G-CML点亮 LED

    前言 用vivado建立工程的时候选择的型号为:XC7K325tffg676-1 在以下代码文件中,仿真与设计都没有问题.在xdc文件中的时钟约束与锁相环配置中还存在问题,没有寻找到解决办法 使用手册 ...

  4. Scrum 冲刺 第七日

    Scrum 冲刺 第七日 站立式会议 燃尽图 今日任务安排 项目发布说明 站立式会议 返回目录 燃尽图 返回目录 今日任务安排 返回目录 项目发布说明 本版本的新功能 不只是简单打地鼠,还有一些不能打 ...

  5. git基本用法

    基本用法(下)           一.实验说明 本节实验为 Git 入门第二个实验,继续练习最常用的git命令. 1.1 实验准备 在进行该实验之前,可以先clone一个练习项目gitproject ...

  6. LR录制脚本的时候打不开浏览器问题

    使用Chrome时,显示开始录制但是Action中无任何脚本,即脚本没成功生成. 使用Firefox(最新版),一直关闭程序,详细信息有StackHash_0a9e. 使用IE11时,也是显示开始录制 ...

  7. vue的简单tab

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...

  8. Win7下安装composer, 并使用其安装smarty

    安装composer需要开启PHP openssl扩展. 1) 先查看PHP是否开启了openssl扩展 键盘win+r 输出cmd, 可以看到Dos窗口, 然后执行php -m (需要添加PHP环境 ...

  9. Python内置函数(5)——pow

    英文文档: pow(x, y[, z]) Return x to the power y; if z is present, return x to the power y, modulo z (co ...

  10. Linux知识积累(5) 关机shutdown和重启reboot

    Linux centos关机与重启命令详解与实战 Linux centos重启命令: 1.reboot 2.shutdown -r now 立刻重启(root用户使用) 3.shutdown -r 1 ...