【题意】

给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠。

【思路】

首先用dijkstra算法构造以1为根的最短路树。

将一条无向边看作两条有向边,考察一条不在最短路树上的边(u,v),如果我们连接(u,v) ,设t=lct(u,v),则为v->t(不含t)路径上的点提供了另外一条1-x的路径且最后一条边不与最短路重合,这条路径长度为dis[u]+dis[v]+e.w-dis[x],对于每个点维护最小的mn=dis[u]+dis[v]+e.w,因为每次需要对一条路径进行修改,所以可以用树链剖分+线段树维护最小值和一个懒标记完成。

好题。。。

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 2e5+;
const int M = 4e5+;
const int inf = 1e9; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Edge {
int u,v,w,nxt;
}e[M];
int en=,front[N];
void adde(int u,int v,int w) {
e[++en]=(Edge){u,v,w,front[u]}; front[u]=en;
} struct Node {
int id,dis;
bool operator < (const Node& rhs) const {
return dis>rhs.dis;
}
}; struct Tnode {
int u,l,r,mn,tag;
void minv(int x);
void pushdown();
void maintain();
}T[N<<];
void Tnode::minv(int x) {
tag=x;
mn=min(mn,x);
}
void Tnode:: pushdown() {
if(tag!=- && l!=r) {
T[u<<].minv(tag);
T[u<<|].minv(tag);
tag=-;
}
}
void Tnode:: maintain() {
if(l==r) return ;
mn=min(T[u<<].mn,T[u<<|].mn);
} priority_queue<Node> q;
int n,m;
int SZ,vis[N],dis[N],dep[N],siz[N],son[N],fa[N],top[N],mark[N],p[N],pl[N]; void dijkstra()
{
FOR(i,,n) dis[i]=inf;
dis[]=;
q.push((Node){,});
while(!q.empty()) {
int u=q.top().id; q.pop();
if(vis[u]) continue;
vis[u]=;
trav(u,i) {
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w) {
dis[v]=dis[u]+e[i].w;
mark[p[v]]=; mark[i]=;
p[v]=i;
q.push((Node){v,dis[v]});
}
}
}
}
void dfs1(int u)
{
siz[u]=; son[u]=;
trav(u,i) if(mark[i]) {
int v=e[i].v;
if(v!=fa[u]) {
fa[v]=u;
dep[v]=dep[u]+;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u,int tp)
{
top[u]=tp; pl[u]=++SZ;
if(son[u]) dfs2(son[u],tp);
trav(u,i) if(mark[i]&&e[i].v!=fa[u])
dfs2(e[i].v,e[i].v);
}
int lca(int u,int v) {
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]? u:v;
}
void build(int u,int l,int r)
{
T[u]=(Tnode) {u,l,r,inf,-};
if(l==r) return ;
int mid=l+r>>;
build(u<<,l,mid),
build(u<<|,mid+,r);
}
void update(int u,int L,int R,int x)
{
T[u].pushdown();
if(L<=T[u].l&&T[u].r<=R) T[u].minv(x);
else {
int mid=T[u].l+T[u].r>>;
if(L<=mid) update(u<<,L,R,x);
if(mid<R) update(u<<|,L,R,x);
T[u].maintain();
}
}
int query(int u,int x)
{
T[u].pushdown();
if(T[u].l==T[u].r) return T[u].mn;
else {
int mid=T[u].l+T[u].r>>;
if(x<=mid) return query(u<<,x);
else return query(u<<|,x);
}
} void modify(int u,int v,int x)
{
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
update(,pl[top[u]],pl[u],x);
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
update(,pl[u],pl[v],x);
} int main()
{
n=read(),m=read();
int u,v,w;
FOR(i,,m) {
u=read(),v=read(),w=read();
adde(u,v,w),adde(v,u,w);
}
dijkstra();
dfs1(),dfs2(,);
build(,,SZ);
for(int i=;i<=en;i+=) {
u=e[i].u,v=e[i].v,w=e[i].w;
int LCA=lca(u,v);
if(!mark[i]) modify(v,LCA,dis[u]+dis[v]+e[i].w);
if(!mark[i^]) modify(u,LCA,dis[u]+dis[v]+e[i].w);
}
FOR(i,,n) {
w=query(,pl[i]);
if(w==inf) puts("-1");
else printf("%d\n",w-dis[i]);
}
return ;
}

bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)的更多相关文章

  1. bzoj 1576: [Usaco2009 Jan]安全路经Travel 树链剖分

    1576: [Usaco2009 Jan]安全路经Travel Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 665  Solved: 227[Sub ...

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

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

  3. bzoj 1576: [Usaco2009 Jan]安全路经Travel——并查集+dijkstra

    Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第i行包含一个数 ...

  4. bzoj 1576: [Usaco2009 Jan]安全路经Travel【spfa+树链剖分+线段树】

    这几天写USACO水题脑子锈住了--上来就贪心,一交就WA 事实上这个是一个叫最短路树的东西,因为能保证只有一条最短路,所以所有最短路合起来是一棵以1为根的树,并且在这棵树上,每个点被精灵占据的路是它 ...

  5. BZOJ.1576.[Usaco2009 Jan]安全路经Travel(树形DP 并查集)

    题目链接 BZOJ 洛谷 先求最短路树.考虑每一条非树边(u,v,len),设w=LCA(u,v),这条边会对w->v上的点x(x!=w)有dis[u]+dis[v]-dis[x]+len的距离 ...

  6. BZOJ 1576: [Usaco2009 Jan]安全路经Travel

    日常自闭半小时后看题解,太弱了qwq. 感觉这道题还是比较难的,解法十分巧妙,不容易想到. 首先题目说了起点到每个点的最短路都是唯一的,那么对这个图求最短路图必定是一棵树,而且这棵树是唯一的. 那么我 ...

  7. 【BZOJ】1576 [Usaco2009 Jan]安全路经Travel

    [算法]最短路树+(树链剖分+线段树)||最短路树+并查集 [题解] 两种方法的思想是一样的,首先题目限制了最短路树唯一. 那么建出最短路树后,就是询问对于每个点断掉父边后重新找路径的最小值,其它路径 ...

  8. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  9. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

随机推荐

  1. ubuntu下显卡管理

    1 Ubuntu下卸载ATI显卡驱动并还原开源驱动[转] 首先卸载已经安装的ATI显卡驱动:cd /usr/share/ati/sudo ./fglrx-uninstall.sh 接着执行下面的代码: ...

  2. Lua表的构造及遍历

    关于lua中的table,主要的困惑来自于table既可以当array用又可以当record用,有时候就会混淆不清. lua中的table貌似是用map来实现的,array是语法糖,一种特例.下面是l ...

  3. 1、Web容器的理解&Tomcat的安装与配置

    Web容器的理解 <Java Web开发实战经典——基础篇>一书中对Web容器这一概念阐述得很好,借用其观点对Web容器加以理解: 想要运行一个Java Web的程序,则必须有相应的Web ...

  4. Android viewPage notifyDataSetChanged无刷新

    转载 http://www.67tgb.com/?p=624 最近项目结束,搞了一次代码分享.其中一位同学分享了一下自己在解决问题过程中的一些心得体会,感觉受益匪浅.整理出来,分享给大家. 建议使用自 ...

  5. Segmentation Fault错误原因总结

    最近在项目上遇到了Segmentation Fault的错误,一直调试不出来是哪里出了问题,对于刚接触嵌入式的,也不知道该如何去调试一个项目,定位内存问题,纠结了好几天,好阿红整理下自己的思路.从头开 ...

  6. Linux线程属性总结

    线程属性标识符:pthread_attr_t 包含在 pthread.h 头文件中. //线程属性结构如下: typedef struct { int                   etachs ...

  7. Jquery 弹出新窗体

    开始先用css将这个DIV设好位置,并且隐藏 function winshow() { var winNode = $(".win"); winNode.show("sl ...

  8. HDU 1425 sort 【哈希入门】

    题意:给出n个数,输出前m大的数 和上一题一样,将输入的数加上一个极大地值作为地址 #include<iostream> #include<cstdio> #include&l ...

  9. Asp.Net多线程用法1

    Asp.Net多线程简单用法 一个web页面 default.aspx 里面有两个控件GridView1,GridView2,通过两个线程分别加载绑定数据. protected void Page_L ...

  10. ASIFormDataRequest实现post的代码示例

    用jquery实现的Post方法可能如下 var param = $.param({ data: JSON.stringify({"from":"234",&q ...