bzoj3694最短路

Description

给出一个n个点m条边的无向图,n个点的编号从1~n,定义源点为1。定义最短路树如下:从源点1经过边集T到任意一点i有且仅有一条路径,且这条路径是整个图1到i的最短路径,边集T构成最短路树。 给出最短路树,求对于除了源点1外的每个点i,求最短路,要求不经过给出的最短路树上的1到i的路径的最后一条边。

 

Input

第一行包含两个数n和m,表示图中有n个点和m条边。

接下来m行,每行有四个数ai,bi,li,ti,表示图中第i条边连接ai和bi权值为li,ti为1表示这条边是最短路树上的边,ti为0表示不是最短路树上的边。

Output

输出n-1个数,第i个数表示从1到i+1的要求的最短路。无法到达输出-1。

Sample Input

5 9

3 1 3 1

1 4 2 1

2 1 6 0

2 3 4 0

5 2 3 0

3 2 2 1

5 3 1 1

3 5 2 0

4 5 4 0

Sample Output

6 7 8 5

HINT

对于100%的数据,n≤4000,m≤100000,1≤li≤100000


solution

我的方法很诡异

首先删一条边相当于把一棵子树孤立出来。

那么答案应要通过其他边绕到子树外面的点,再回到根。

我们记d[i][j]表示以i为根的子树到其他点的最短路。

可以用类似树形dp的方法把儿子的信息合并上来。

O(n^2+m)

其他方法

考虑一条非树边,假设它连接了u,v

那么他可以贡献的段为u~lca,u~lca

树剖维护

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define maxn 4005
#define inf 1e9
using namespace std;
int n,m,t1,t2,t3,t4,head[maxn],tot=1;
int d[maxn][maxn],ans[maxn];
int dfst[maxn],dfsn[maxn],sc,len[maxn],flag[maxn];
struct node{
int v,nex,w,op;
}e[200005];
void lj(int t1,int t2,int t3,int t4){
e[++tot].v=t2;e[tot].w=t3;e[tot].op=t4;e[tot].nex=head[t1];head[t1]=tot;
}
void DFS(int k,int fa){
dfst[k]=++sc;
for(int i=head[k];i;i=e[i].nex){
if(!e[i].op||e[i].v==fa)continue;
len[e[i].v]=len[k]+e[i].w;
DFS(e[i].v,k);
}
dfsn[k]=sc;
}
void dfs(int k,int fa,int b){
for(int i=head[k];i;i=e[i].nex){
if(!e[i].op||e[i].v==fa)continue;
dfs(e[i].v,k,i);
}
for(int i=1;i<=n;i++)d[k][i]=inf;
for(int i=head[k];i;i=e[i].nex){
if(!e[i].op||e[i].v==fa)continue;
for(int x=1;x<=n;x++)d[k][x]=min(d[k][x],d[e[i].v][x]+e[i].w);
flag[e[i].v]=1;
}//合并子树
for(int i=head[k];i;i=e[i].nex){
if(i==(b^1))continue;
d[k][e[i].v]=min(d[k][e[i].v],e[i].w);
}// itself
int l=dfst[k],r=dfsn[k];
//cout<<"k: "<<k<<endl;
ans[k]=inf;
for(int x=1;x<=n;x++){
//cout<<d[k][x]<<' ';
if(dfst[x]<l||dfst[x]>r){
ans[k]=min(ans[k],d[k][x]+len[x]);
}
}//cout<<endl;
for(int i=head[k];i;i=e[i].nex){
flag[e[i].v]=0;
}
}
int main()
{
freopen("shortest.in","r",stdin);
freopen("shortest.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
lj(t1,t2,t3,t4);lj(t2,t1,t3,t4);
}
DFS(1,0);
//for(int k=1;k<=n;k++)cout<<k<<' '<<len[k]<<' '<<dfst[k]<<endl;
dfs(1,0,0);
if(ans[2]!=inf)printf("%d",ans[2]);
else printf("-1");
for(int i=3;i<=n;i++){
if(ans[i]==inf)printf(" -1");
else printf(" %d",ans[i]);
}
puts("");
return 0;
}

bzoj3694最短路的更多相关文章

  1. [bzoj3694]最短路_树链剖分_线段树

    最短路 bzoj-3694 题目大意:给你一个n个点m条边的无向图,源点为1,并且以点1为根给出最短路树.求对于2到n的每个点i,求最短路,要求不经过给出的最短路树上的1到i的路径上的最后一条边. 注 ...

  2. [bzoj3694]最短路

    Description 给出一个$n$个点$m$条边的无向图,$n$个点的编号从$1-n$,定义源点为$1$. 定义最短路树如下:从源点$1$经过边集$T$到任意一点$i$有且仅有一条路径,且这条路径 ...

  3. bzoj3694: 最短路(树链剖分/并查集)

    bzoj1576的帮我们跑好最短路版本23333(双倍经验!嘿嘿嘿 这题可以用树链剖分或并查集写.树链剖分非常显然,并查集的写法比较妙,涨了个姿势,原来并查集的路径压缩还能这么用... 首先对于不在最 ...

  4. 「BZOJ3694」「FJ2014集训」最短路

    「BZOJ3694」「FJ2014集训」最短路 首先树剖没得说了,这里说一下并查集的做法, 对于一条非树边,它会影响的点就只有u(i),v(i)到lca,对于lca-v的路径上所有点x,都可通过1-t ...

  5. 最短路 BZOJ3694 树链剖分+线段树

    分析: 树剖裸题,[Usaco2009 Jan]安全路经Travel 的简化版 剖开最短路树,遍历每一条没在最短路树上的边. 这种情况下,有且仅有u到v路径上,出来lca之外的点能够通过这条边到达,并 ...

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

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

  7. bzoj1001--最大流转最短路

    http://www.lydsy.com/JudgeOnline/problem.php?id=1001 思路:这应该算是经典的最大流求最小割吧.不过题目中n,m<=1000,用最大流会TLE, ...

  8. 【USACO 3.2】Sweet Butter(最短路)

    题意 一个联通图里给定若干个点,求他们到某点距离之和的最小值. 题解 枚举到的某点,然后优先队列优化的dijkstra求最短路,把给定的点到其的最短路加起来,更新最小值.复杂度是\(O(NElogE) ...

  9. Sicily 1031: Campus (最短路)

    这是一道典型的最短路问题,直接用Dijkstra算法便可求解,主要是需要考虑输入的点是不是在已给出的地图中,具体看代码 #include<bits/stdc++.h> #define MA ...

随机推荐

  1. ubuntu install oracle jdk

    .Download the required tarball from here .unzip this tarball using "tar -zxvf tarball_name .cre ...

  2. Java中的异常处理从概念到实例

    1.概念 采用新的异常处理机制 在以往的程序开发过程中,经常采用返回值进行处理.例如,在编写一个方法,可以返回一个状态代码,调用者根据状态代码判定出错与否.若状态代码表示一个错误,则调用这进行相应的处 ...

  3. Arguments Optional-freecodecamp算法题目

    Arguments Optional 1.要求 创建一个计算两个参数之和的 function.如果只有一个参数,则返回一个 function,该 function 请求一个参数然后返回求和的结果. 如 ...

  4. 二、C到C++的升级

    C++ 的加强主要表现在:类型的加强.面向对象支持 1.C++改进 C++更强调语言的实用性,所有的变量都可以再需要使用的时候再定义,C语言中的变量都必须在作用域开始的位置定义 int c = 0; ...

  5. 线段树和zkw线段树

    作者作为一个蒟蒻,也是最近才自学了线段树,不对的地方欢迎大佬们评论,但是不要喷谢谢 好啦,我们就开始说说线段树吧 线段树是个支持区间操作和查询的东东,平时的话还是蛮实用的 下面以最基本的区间加以及查询 ...

  6. lrzsz包中的rz和sz命令

    安装包:lrzsz rz命令:将物理机文件复制到虚拟机 sz命令:将虚拟机文件复制到物理机

  7. 【Django】Django开发中的日志输出

    开发环境:Ubuntu16.04+Django 1.11.9+Python2.7 一:使用自定义函数输出日志到log文件: import time def print_log(log): file_o ...

  8. 六、MySQL 删除数据库

    MySQL 删除数据库 使用普通用户登陆 MySQL 服务器,你可能需要特定的权限来创建或者删除 MySQL 数据库,所以我们这边使用 root 用户登录,root 用户拥有最高权限. 在删除数据库过 ...

  9. I Like for You to Be Still【我会一直喜欢你】

    I Like for You to Be Still I like for you to be still 我会一直喜欢这你 It is as though you are absent 就算你并不在 ...

  10. JVM——Java类加载机制总结

    )解析:解析阶段是把虚拟机中常量池的符号引用替换为直接引用的过程. 2.3 初始化 类初始化时类加载的最后一步,前面除了加载阶段用户可以通过自定义类加载器参与以外,其余都是虚拟机主导和控制.到了初始化 ...