[usaco jan 09] 安全路径 travel [最短路径树]
题面:
思路:
既然最后一条边不能走,那么就一定是换了一条路,一条不经过这最后一条边的路
如果想要这条路最短,那么其在路上一定尽可能多地走了最短路径
因此,我们对这张图跑一遍从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 [最短路径树]的更多相关文章
- [usaco jan 09] 气象牛 baric [dp]
题面: 传送门 思路: 题意有点绕,实际上就是给你一个计算规则,让你取最少的元素,通过这个计算方式,得到一个小于指定误差上限的结果 这个规则分为三个部分,这里分别用pre,sum,suf表示 因为给定 ...
- [BZOJ1576] [BZOJ3694] [USACO2009Jan] 安全路径(最短路径+树链剖分)
[BZOJ1576] [BZOJ3694] [USACO2009Jan] 安全路径(最短路径+树链剖分) 题面 BZOJ1576和BZOJ3694几乎一模一样,只是BZOJ3694直接给出了最短路树 ...
- [BZOJ 1576] [Usaco2009 Jan] 安全路经Travel 【树链剖分】
题目链接: BZOJ - 1576 题目分析 首先Orz Hzwer的题解. 先使用 dijikstra 求出最短路径树. 那么对于一条不在最短路径树上的边 (u -> v, w) 我们可以先沿 ...
- 【最短路径树】51nod1443 路径和树
并不是什么高端操作并且一些模型会用到 Description 给定一幅无向带权连通图G = (V, E) (这里V是点集,E是边集).从点u开始的最短路径树是这样一幅图G1 = (V, E1),其中E ...
- 安全路径——最短路径树+dsu缩边
题目描述 思路 首先想到$dijkstra$跑完之后$build$一棵最短路径树.要找到每个节点i到根的满足要求的最短路,考虑把一些非树边加进去. 对于非树边$(u,v)$,因为节点i上方的边被占领, ...
- bzoj 4016: [FJOI2014]最短路径树问题
bzoj4016 最短路路径问题 Time Limit: 5 Sec Memory Limit: 512 MB Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点 ...
- [BZOJ4016][FJOI2014]最短路径树问题
[BZOJ4016][FJOI2014]最短路径树问题 试题描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长 ...
- HDU4871 Shortest-path tree(最短路径树 + 树的点分治)
题目大概要先求一张边有权的图的根为1的最短路径树,要满足根到各点路径序列的字典序最小:然后求这棵最短路径树包含k个结点的最长路径的长度和个数. 首先先构造出这棵字典序最小的最短路径树..好吧,我太傻逼 ...
- POJ3013 Big Christmas Tree(最短路径树)
题目大概说给一张点和边都有权的图,现在要求其一棵以1结点为根的生成树使树的边权和最小,树边权 = 对应的图边权 * 树边末端点为根的子树所有结点对于图顶点的点权和. 要求∑(边权*子树点权和),等价于 ...
随机推荐
- 在RichTextBox控件中替换文本文字
实现效果: 知识运用: RichTextBox控件的SelectedText属性 实现代码: private void button1_Click(object sender, EventArgs e ...
- 推荐一个WebIDE在线编程语言编译器C9.io
有时借用别人电脑或者不想在电脑上安装各种乱七八糟的IDE,就可以考虑 Web IDE.随着Web技术发展,很多语言的编译工作都可以利用Web 浏览器来完成. 1. 推荐国外的 C9.io 个人可以免费 ...
- Java之JDK的下载与安装,java环境变量的配置,Editplus的下载与使用
JRE(Java Runtime Environment Java运行环境) 包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一个开发 ...
- linux系统串口编程实例
在嵌入式开发中一些设备如WiFi.蓝牙......都会通过串口进行主机与从机间通信,串口一般以每次1bit位进行传输,效率相对慢. 在linux系统下串口的编程有如下几个步骤,最主要的是串口初始化! ...
- 你不知道的c++11
随着C++11的发布,C++这门语言有了本质上的提升.C++14,C++17的相继推出,更是让C++这门语言达到了一个新高度.新的标准库设施,新的语法,让我们得以书写更加安全.便捷.高效的程序. 20 ...
- Java - Java 中的三种 ClassLoader
1.虚拟机类加载器(称为“bootstrap class loader”),它本身没有父类加载器,它负责加载虚拟机的内置类,由于它是用C.C++写的,所以Java无法拿到其class文件,返回的都是空 ...
- MySQL-Xtrabackup备份还原
前言 通常我们都是使用xtrabackup工具来备份数据库,它是一个专业的备份工具,先来简单介绍下它. Xtrabackup percona提供的mysql数据库备份工具,惟一开源的能够对innodb ...
- (新手)使用pandas操作EXCEL
import pandas as pdimport numpy as npfrom pandas import DataFrame,Series#path = r'C:\Users\tsl\Deskt ...
- mysql同步故障解决
故障现象:Slave_SQL_Running: No Slave状态:mysql> show slave status\GSlave_IO_Running: YesSlave_SQL_Runni ...
- python集成开发环境PyCharm
环境安装视频介绍:http://pan.baidu.com/s/1gfz6wiZ ppmb 外加几个截图: activate: