题面:

传送门

思路:

既然最后一条边不能走,那么就一定是换了一条路,一条不经过这最后一条边的路

如果想要这条路最短,那么其在路上一定尽可能多地走了最短路径

因此,我们对这张图跑一遍从1开始的单源最短路,并建立出最短路径树

那么新的路径(1->u)一定是这样构成的:(1->v)+edge(v,w)+(w->u),其中w是u在最短路径树上的后代

那么,我们对于每一条非树边(u,v),其树上路径上所有点(除了lca)的答案,都可以被dis[u]+dis[v]+w(u,v)-dis[路径上的点]来更新

然而,直接每一次这样更新,时间效率肯定不行

对上述的结论进一步分析,可以发现,实际上dis[u]+dis[v]+w(u,v)对于每条非树边(u,v)固定

因此可以把dis[u]+dis[v]+w(u,v)排序,对于每一条非树边依次操作,并且使用并查集来跳过已经更新过得边

总时间复杂度:dij O(nlogn),排序 O(mlogm) 更新答案 O(n)

Code:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
struct edge{
int to,w,next;
}e[];
struct new_edge{
int from,to,w;
}x[];
struct node{
int num,fa;
vector<int>son;
}a[];
int n,m,first[],pre[],dis[],f[],ans[];
bool vis[];
void spfa(){
int i,u,v,w;
queue<int>q;memset(dis,,sizeof(dis));
q.push();pre[]=;dis[]=;
while(!q.empty()){
u=q.front();q.pop();vis[u]=;
for(i=first[u];~i;i=e[i].next){
v=e[i].to;w=e[i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;pre[v]=u;
if(!vis[v]){
vis[v]=;q.push(v);
}
}
}
}
}
bool cmp(new_edge l,new_edge r){
return l.w<r.w;
}
int find(int x){
return ((f[x]==x)?x:f[x]=find(f[x]));
}
int aa[],bb[],cc[];
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
memset(first,-,sizeof(first));
memset(ans,-,sizeof(ans));
int i,j,t1,t2,t3,l,r;
scanf("%d%d",&n,&m);
for(i=;i<=m;i++){
scanf("%d%d%d",&t1,&t2,&t3);
e[i*-].to=t2;e[i*-].next=first[t1];e[i*-].w=t3;first[t1]=i*-;
e[i*].to=t1;e[i*].next=first[t2];e[i*].w=t3;first[t2]=i*;
aa[i]=t1;bb[i]=t2;cc[i]=t3;
}
spfa();
// for(i=1;i<=n;i++) cout<<pre[i]<<ends<<dis[i]<<endl;
// for(i=1;i<=m;i++) cout<<aa[i]<<ends<<bb[i]<<ends<<cc[i]<<endl;
// cout<<"end of spfa"<<endl;
for(i=;i<=n;i++){
a[i].num=i;f[i]=i;
a[i].fa=pre[i];
if(i!=) a[pre[i]].son.push_back(i);
}
int cnt=;
for(i=;i<=m;i++){
if(pre[aa[i]]==bb[i]||pre[bb[i]]==aa[i]) continue;
// cout<<aa[i]<<ends<<bb[i]<<ends<<cc[i]<<endl;
x[++cnt].from=aa[i];x[cnt].to=bb[i];x[cnt].w=dis[aa[i]]+dis[bb[i]]+cc[i];
}
// cout<<"end2"<<endl;
sort(x+,x+cnt+,cmp);
for(i=;i<=cnt;i++){
l=find(x[i].from);r=find(x[i].to);
while(l!=r){
if(dis[l]<dis[r]) swap(l,r);
ans[l]=x[i].w-dis[l];
f[l]=pre[l];l=find(l);
}
}
for(i=;i<=n;i++) printf("%d\n",ans[i]);
}

[usaco jan 09] 安全路径 travel [最短路径树]的更多相关文章

  1. [usaco jan 09] 气象牛 baric [dp]

    题面: 传送门 思路: 题意有点绕,实际上就是给你一个计算规则,让你取最少的元素,通过这个计算方式,得到一个小于指定误差上限的结果 这个规则分为三个部分,这里分别用pre,sum,suf表示 因为给定 ...

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

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

  3. [BZOJ 1576] [Usaco2009 Jan] 安全路经Travel 【树链剖分】

    题目链接: BZOJ - 1576 题目分析 首先Orz Hzwer的题解. 先使用 dijikstra 求出最短路径树. 那么对于一条不在最短路径树上的边 (u -> v, w) 我们可以先沿 ...

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

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

  5. 安全路径——最短路径树+dsu缩边

    题目描述 思路 首先想到$dijkstra$跑完之后$build$一棵最短路径树.要找到每个节点i到根的满足要求的最短路,考虑把一些非树边加进去. 对于非树边$(u,v)$,因为节点i上方的边被占领, ...

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

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

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

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

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

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

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

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

随机推荐

  1. 【转】Nginx搭建反向代理服务器过程详解

    阅读目录 1.1 反向代理初印象 1.2 反向代理的作用 2.1 Nginx是神马? 2.2 Nginx的应用现状 2.3 Nginx的核心特点 3.1 准备一个ASP.NET网站部署到IIS服务器集 ...

  2. C#图片上传获取二进制流保存至AD

    <form id="form1" runat="server"> <div> <asp:FileUpload ID="F ...

  3. 黑马基础阶段测试题:定义一个int类型的数组,数组中元素为{5,7,3,9,4}。求出数组中的最小值,并判断最小值是否为偶数,如果是偶数则输出“最小值为偶数”,如果不是偶数则输出“最小值为奇数”。打印如下:

    package com.swift; import java.util.Arrays; public class ArrayTest { public static void main(String[ ...

  4. 关于小程序button控件上下边框的显示和隐藏问题

    问题: 小程序的button控件上下有一条淡灰色的边框,在空件上加上了样式 border:(none/0); 都没办法让button上下的的边框隐藏: 代码如下 <button class=&q ...

  5. 入门学习Linux常用必会命令实例详解

    Linux提供了大量的命令,利用它可以有效地完成大量的工作,如磁盘操作.文件存取.目录操作.进程管理.文件权限设定等.所以,在Linux系统上工作离不开使用系统提供的命令.要想真正理解Linux系统, ...

  6. Install Jenkins 2.1.36 and openjdk 1.7.0 on centos 7

    #!/bin/bash## Copyright (c) 2014-2015 Michael Dichirico (https://github.com/mdichirico)# This softwa ...

  7. linux配置邮箱服务

    配置邮箱服务Linux常见的邮箱客户端是mail或mutt:服务端有sendmail服务(centos 5).postfix服务(centos 6).这里我们不使用本地的邮件服务,而是使用本地的邮件客 ...

  8. hadoop核心组件概述及hadoop集群的搭建

    什么是hadoop? Hadoop 是 Apache 旗下的一个用 java 语言实现开源软件框架,是一个开发和运行处理大规模数据的软件平台.允许使用简单的编程模型在大量计算机集群上对大型数据集进行分 ...

  9. Database returned an invalid datetime value. Are time zone definitions for your database installed?

    在做文章归档的会后,打印结果时报了这个错误 ret = models.Article.objects.filter(user=user).annotate(month=TruncMonth('crea ...

  10. A1083 List Grades (25)(25 分)

    A1083 List Grades (25)(25 分) Given a list of N student records with name, ID and grade. You are supp ...