题目描述

思路

首先想到$dijkstra$跑完之后$build$一棵最短路径树。要找到每个节点i到根的满足要求的最短路,考虑把一些非树边加进去。

对于非树边$(u,v)$,因为节点i上方的边被占领,所以只能选择往下走,从非树边走到别的子树,设$u$属于$i$的子树,$v$不属于,那么$u,v$的$lca$经过$i$,且$i$经过$(u,v)$到根的最短路为$dist[u]+dist[v]-dist[i]+w(u,v)$,这样我们把每条非树边按照$dist[u]+dist[v]+w(u,v)$排序,并查集把$(u,v)$覆盖的边缩起来乱搞一下,从$u,v$不断往上跳即可。

code

#include<iostream>
#include<vector>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define pii pair<int,int>
#define mp(x,y) make_pair(x,y)
using namespace std;
const int N=;
const int M=;
const int inf=<<;
struct node
{
int from,next,to,dis;
}g1[M<<],g[N<<];
int h1[N],cnt1;
int head[N],cnt;
int n,m;
int f[N]; inline void addedge1(int u,int v,int dis)
{
g1[++cnt1].next=h1[u];
g1[cnt1].to=v;
g1[cnt1].from=u;
g1[cnt1].dis=dis;
h1[u]=cnt1;
} inline void addedge(int u,int v,int dis)
{
g[++cnt].next=head[u];
g[cnt].to=v;
g[cnt].dis=dis;
head[u]=cnt;
} inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} int dist[N],dep[N];
bool vis[N],on_tree[M<<];
inline void dijkstra(int s)
{
priority_queue<pii,vector<pii>,greater<pii> >q;
for(int i=;i<=n;i++)vis[i]=,dist[i]=inf;
dist[s]=;q.push(mp(,s));
while(!q.empty())
{
int u=q.top().second;q.pop();
if(vis[u])continue;
vis[u]=;
for(int i=h1[u];i;i=g1[i].next)
{
int v=g1[i].to;
if(dist[v]>dist[u]+g1[i].dis)
{
dist[v]=dist[u]+g1[i].dis;
if(!vis[v])q.push(mp(dist[v],v));
}
}
}
} inline void bt(int u)
{
dep[u]=dep[f[u]]+;
for(int i=h1[u];i;i=g1[i].next)
{
int v=g1[i].to;
if(v==f[u])continue;
if(dist[v]==dist[u]+g1[i].dis)
f[v]=u,bt(v),addedge(u,v,g1[i].dis),addedge(v,u,g1[i].dis),on_tree[i]=on_tree[i^]=;
}
} struct not_tree
{
int u,v,w,len;
}e[M];
int tot=;
int ans[N]; bool cmp(not_tree a,not_tree b)
{
return a.len<b.len;
} struct DSU
{
int father[N];
inline void init(int x){for(int i=;i<=x;i++)father[i]=i;}
inline int find(int x){return x==father[x]?x:father[x]=find(father[x]);}
inline void merge(int x,int y){int r1=find(x),r2=find(y);father[r1]=r2;}
}dsu; inline void cover(int x,int y,int len)
{
x=dsu.find(x);y=dsu.find(y);
while(x!=y)
{
if(dep[x]<dep[y])swap(x,y);
dsu.merge(x,f[x]);
ans[x]=len-dist[x];
x=dsu.find(f[x]);
}
} int main()
{
n=read();m=read();
for(int i=;i<=m;i++)
{
int x=read(),y=read(),z=read();
addedge1(x,y,z);addedge1(y,x,z);
}
dijkstra();
bt();
for(int i=;i<=cnt1;i+=)
{
if(on_tree[i])continue;
int u=g1[i].from,v=g1[i].to,d=g1[i].dis;
e[++tot]=(not_tree){u,v,d,dist[u]+dist[v]+d};
}
sort(e+,e++tot,cmp);
dsu.init(n);
memset(ans,-,sizeof(ans));
for(int i=;i<=tot;i++)
{
cover(e[i].u,e[i].v,e[i].len);
}
for(int i=;i<=n;i++)
{
if(ans[i]!=-)printf("%d\n",ans[i]);
else printf("-1\n");
} }

安全路径——最短路径树+dsu缩边的更多相关文章

  1. [BZOJ1576] [BZOJ3694] [USACO2009Jan] 安全路径(最短路径+树链剖分)

    [BZOJ1576] [BZOJ3694] [USACO2009Jan] 安全路径(最短路径+树链剖分) 题面 BZOJ1576和BZOJ3694几乎一模一样,只是BZOJ3694直接给出了最短路树 ...

  2. [usaco jan 09] 安全路径 travel [最短路径树]

    题面: 传送门 思路: 既然最后一条边不能走,那么就一定是换了一条路,一条不经过这最后一条边的路 如果想要这条路最短,那么其在路上一定尽可能多地走了最短路径 因此,我们对这张图跑一遍从1开始的单源最短 ...

  3. 【最短路径树】51nod1443 路径和树

    并不是什么高端操作并且一些模型会用到 Description 给定一幅无向带权连通图G = (V, E) (这里V是点集,E是边集).从点u开始的最短路径树是这样一幅图G1 = (V, E1),其中E ...

  4. bzoj 4016: [FJOI2014]最短路径树问题

    bzoj4016 最短路路径问题 Time Limit: 5 Sec Memory Limit: 512 MB Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点 ...

  5. [BZOJ4016][FJOI2014]最短路径树问题

    [BZOJ4016][FJOI2014]最短路径树问题 试题描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长 ...

  6. HDU4871 Shortest-path tree(最短路径树 + 树的点分治)

    题目大概要先求一张边有权的图的根为1的最短路径树,要满足根到各点路径序列的字典序最小:然后求这棵最短路径树包含k个结点的最长路径的长度和个数. 首先先构造出这棵字典序最小的最短路径树..好吧,我太傻逼 ...

  7. POJ3013 Big Christmas Tree(最短路径树)

    题目大概说给一张点和边都有权的图,现在要求其一棵以1结点为根的生成树使树的边权和最小,树边权 = 对应的图边权 * 树边末端点为根的子树所有结点对于图顶点的点权和. 要求∑(边权*子树点权和),等价于 ...

  8. bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)

    4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 426  Solved: 147[Submit][Stat ...

  9. [FJOI 2014]最短路径树问题

    Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最 ...

随机推荐

  1. Solidity 编程实例--投票

    Voting 投票 思路是为每张选票创建一个合约,每个投票选项提供一个短名称.合约创建者作为会长将会给每个投票参与人各自的地址投票权. 地址后面的人们可以选择自己投票或者委托信任的代表人替他们投票.在 ...

  2. pycharm 2019/10 激活码 最新福利 (1)

    MTW881U3Z5-eyJsaWNlbnNlSWQiOiJNVFc4ODFVM1o1IiwibGljZW5zZWVOYW1lIjoiTnNzIEltIiwiYXNzaWduZWVOYW1lIjoiI ...

  3. Java读源码之LockSupport

    前言 JDK版本: 1.8 作用 LockSupport类主要提供了park和unpark两个native方法,用于阻塞和唤醒线程.注释中有这么一段: 这个类是为拥有更高级别抽象的并发类服务的,开发中 ...

  4. numpy.rollaxis函数

    numpy.rollaxis numpy.rollaxis 函数向后滚动特定的轴到一个特定位置,格式如下: numpy.rollaxis(arr, axis, start) 参数说明: arr:数组 ...

  5. MySQL逻辑架构、SQL加载执行顺序、七种JOIN模式图解

    逻辑架构   存储引擎 查看当前安装的mysql提供的存储引擎 查看当前mysql默认的存储引擎 MyISAM和InnoDB SQL加载执行顺序 sql书写顺序 mysql解析器执行的顺序  考点:m ...

  6. repr() Vs str()

    在python中,将对象转换为字符串有两个内建函数: str Vs repr .str 是一个友好的,人们可读的字符串.repr 应该包含关于对象内容的详细信息(有时他们会返回相同的内容,例如整数). ...

  7. 2019头条java面试总结 (包含面试题解析)

    2019滴滴java面试总结  (包含面试题) 本人8年开发经验.今年年初找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.滴滴等公司offer,岗位是Java后端开发. 面试了很多家公司,感觉大部分 ...

  8. Django与drf 源码视图解析

    0902自我总结 Django 与drf 源码视图解析 一.原生Django CBV 源码分析:View """ 1)as_view()是入口,得到view函数地址 2) ...

  9. 代码审计-EasyCMS

    cms来源AWD线下攻防平台题目.  链接:https://pan.baidu.com/s/1eUkyRspQmsv-0fIBby8ZlQ  提取码:tywa 失效可以联系我   0x01 文件上传漏 ...

  10. 数据挖掘:python数据清洗cvs里面带中文字符

    数据清洗,使用python数据清洗cvs里面带中文字符,意图是用字典对应中文字符,即key值是中文字符,value值是index,自增即可:利用字典数据结构没有重复key值的特性,把中文字符映射到了数 ...