1576: [Usaco2009 Jan]安全路经Travel

Time Limit: 10 Sec  Memory Limit: 64 MB

Submit: 665  Solved: 227
[Submit][Status]

Description

Input

* 第一行: 两个空格分开的数, N和M

* 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i

Output

* 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1.

Sample Input

4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3

输入解释:

跟题中例子相同

Sample Output

3
3
6

输出解释:

跟题中例子相同

HINT

 

Source

  这道题本来的思路是对于每个子树维护一个单调队列,但是看着写链剖都能T的那么惨,还是老老实实写链剖吧。
  这道题给我最大的启示是:最短路用spfa是非常作死的。。。。。不过以前我都默认spfa最坏为nlogn的。
  至少我一整个下午都没有想到usaco的题居然还要卡spfa。
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 110000
#define MAXQ MAXN*20
#define MAXE (MAXN*4 +MAXN*2)
#define MAXV MAXN
#define INF 0x3f3f3f3f
#define lch (now<<1)
#define rch (now<<1^1)
int n,m;
inline int nextInt()
{
register int x=;
register char ch;
while (ch=getchar(),ch<'' || ch>'');
while (x=x*+ch-'',ch=getchar(),ch<='' && ch>='');
return x;
}
struct sgt_node
{
int l,r,val,lazy;
}sgt[MAXN*];
inline void down(int now)
{
sgt[lch].val=min(sgt[lch].val,sgt[now].val);
sgt[rch].val=min(sgt[rch].val,sgt[now].val);
}
void Build_sgt(int now,int l,int r)
{
sgt[now].l=l;sgt[now].r=r;
if (sgt[now].l==sgt[now].r)
{
sgt[now].val=INF;
return ;
}
Build_sgt(lch,l,(l+r)>>);
Build_sgt(rch,((l+r)>>)+,r);
sgt[now].val=max(sgt[lch].val,sgt[rch].val);
}
void Modify_sgt(int now,int l,int r,int v)
{
if (sgt[now].l==l && sgt[now].r==r)
{
sgt[now].val=min(sgt[now].val,v);
return ;
}
down(now);
int mid=(sgt[now].l+sgt[now].r)>>;
if (r<=mid)
Modify_sgt(lch,l,r,v);
else if (mid<l)
Modify_sgt(rch,l,r,v);
else
Modify_sgt(lch,l,mid,v),Modify_sgt(rch,mid+,r,v);
}
int Query_sgt(int now,int pos)
{
if (sgt[now].l==sgt[now].r)return sgt[now].val;
if (pos<=((sgt[now].l+sgt[now].r)>>))
return min(sgt[now].val,Query_sgt(lch,pos));
else
return min(sgt[now].val,Query_sgt(rch,pos));
}
struct Edge
{
int np,val;
Edge *next;
Edge *neg;
}E[MAXE],*V[MAXV],*V2[MAXV];
int tope=-;
inline void addedge(int x,int y,int z)
{
E[++tope].np=y;
E[tope].val=z;
E[tope].next=V[x];
V[x]=&E[tope];
}
inline void addedge2(int x,int y,int z)
{
E[++tope].np=y;
E[tope].val=z;
E[tope].next=V2[x];
V2[x]=&E[tope];
}
int q[MAXQ];
bool vis[MAXN];
int pnt[MAXN];
int dis[MAXN];
Edge *pne[MAXN];
/*
void spfa(register int now)
{
register int head=-1,tail=0;
memset(dis,INF,sizeof(dis));
q[0]=now;
dis[now]=0;
register Edge *ne;
while (head!=tail)
{
head++;
if (head==MAXQ)head=0;
now=q[head];
vis[now]=false;
for (ne=V[now];ne;ne=ne->next)
{
if (dis[ne->np]>dis[now]+ne->val)
{
dis[ne->np]=dis[now]+ne->val;
pne[ne->np]=ne->neg;
pnt[ne->np]=now;
if (!vis[ne->np])
{
tail++;
if (tail==MAXQ)tail=0;
q[tail]=ne->np;
vis[ne->np]=true;
}
}
}
}
}*/
pair<int,int> h[MAXQ];
void dijkstrea(int now)
{
memset(dis,INF,sizeof(dis));
dis[now]=;
int toph=;
Edge *ne;
h[toph]=make_pair(-,now);
push_heap(h,h+(++toph));
while (~toph)
{
if (h[].first!=-dis[h[].second])
{
pop_heap(h,h+(toph--));
continue;
}
for (ne=V[h[].second];ne;ne=ne->next)
{
if (dis[ne->np]>dis[h[].second] + ne->val)
{
dis[ne->np]=dis[h[].second]+ne->val;
pnt[ne->np]=h[].second;
pne[ne->np]=ne->neg;
h[toph]=make_pair(-dis[ne->np],ne->np);
push_heap(h,h+(++toph));
}
}
pop_heap(h,h+(toph--));
}
}
int son[MAXN];
int top[MAXN];
int depth[MAXN];
int pos[MAXN],dfstime=;
int dfs1(int now)
{
register Edge *ne;
int mxsiz=;
int siz=,t;
for (ne=V2[now];ne;ne=ne->next)
{
depth[ne->np]=depth[now]+;
siz+=t=dfs1(ne->np);
if (t>mxsiz)
{
mxsiz=t;
son[now]=ne->np;
}
}
return siz;
}
void dfs2(int now,int tp)
{
register Edge *ne;
pos[now]=++dfstime;
top[now]=tp;
if (~son[now])
dfs2(son[now],tp);
for (ne=V2[now];ne;ne=ne->next)
{
if (ne->np==son[now])continue;
dfs2(ne->np,ne->np);
}
}
int lca(register int x,register int y)
{
while (x!=y)
{
if (top[x]==top[y])
{
if (depth[x]<depth[y])return x;
else return y;
}
if (depth[top[x]]<depth[top[y]])swap(x,y);
x=pnt[top[x]];
}
return x;
}
void work()
{
register Edge *ne;
register int now,i,d,t;
for (i=;i<=n;i++)
{
for(ne=V[i];ne;ne=ne->next)
{
now=i;
if (ne==pne[now])continue;
d=dis[ne->np]+ne->val +dis[now];
t=lca(ne->np,now);
if (t==now)continue;
while (true)
{
if (depth[top[now]]==depth[top[t]])
{
if (pos[t]+<=pos[now])
Modify_sgt(,pos[t]+,pos[now],d);
break;
}
Modify_sgt(,pos[top[now]],pos[now],d);
now=pnt[top[now]];
}
}
}
int ans;
for (i=;i<=n;i++)
{
ans=-dis[i]+Query_sgt(,pos[i]);
if (ans+dis[i]==INF)
printf("-1\n");
else
printf("%d\n",ans);
}
}
int main()
{
freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int i,j,k,x,y,z;
n=nextInt();m=nextInt();
for (i=;i<m;i++)
{
x=nextInt(),y=nextInt(),z=nextInt();
addedge(x,y,z);
addedge(y,x,z);
V[x]->neg=V[y];
V[y]->neg=V[x];
}
dijkstrea();
memset(son,-,sizeof(son));
for (i=;i<=n;i++)
addedge2(pnt[i],i,INF);
dfs1();
dfs2(,);
Build_sgt(,,dfstime);
work();
}

bzoj 1576: [Usaco2009 Jan]安全路经Travel 树链剖分的更多相关文章

  1. BZOJ1576: [Usaco2009 Jan]安全路经Travel(树链剖分)

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

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

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

  3. bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)

    [题意] 给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠. [思路] 首先用dijkstra算法构造以1为根的最短路树. 将一条无向边看作两条有向边,考察一条不在最短路树上 ...

  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——并查集+dijkstra

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

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

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

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

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

  9. 【BZOJ1576】[Usaco2009 Jan]安全路经Travel 最短路+并查集

    [BZOJ1576][Usaco2009 Jan]安全路经Travel Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, ...

随机推荐

  1. iOS项目进行测试的配置

    一.首先,注册苹果开发者账号并登陆https://developer.apple.com/account/#/overview/ZFBE9NJZM6, 二.创建测试证书

  2. 页面常见效果js实现

    2015.12.2 页面常见效果js实现 [有没有觉得很坑,[笑哭,邮箱写上]] 复习: Js内置对象: 1.浏览器对象 window document history location event  ...

  3. Ubuntu14.04 固定IP

    Ubuntu 固定IP 1. 更改/etc/network/interfaces的内容 1.1 注释掉原来的内容 1.2 添加以下内容 auto eth0 iface eth0 inet static ...

  4. Nginx高性能服务器安装、配置、运维 (3) —— Nginx配置详解

    四.Nginx 配置详解 YUM方式安装的Nginx默认配置文件放在/etc/nginx目录下,使用Vim编辑/etc/nginx/nginx.conf: ---------------------- ...

  5. 在Vivado中调用ModelSim生成FSM的状态转移图

    如果我们已经书写了一段FSM代码,现在想倒过来把它转换成为状态转移图,方便我们直观地检查我们书写的状态对不对(在写论文什么的画图太麻烦的时候,有个自动生成的是多方便啊!),应该怎么弄呢?通过在Viva ...

  6. 玩转html5<canvas>画图

    导航 前言 基本知识 绘制矩形 清除矩形区域 圆弧 路径 绘制线段 绘制贝塞尔曲线 线性渐变 径向渐变(发散) 图形变形(平移.旋转.缩放) 矩阵变换(图形变形的机制) 图形组合 给图形绘制阴影 绘制 ...

  7. ios开发中button控件的属性及常见问题

    最为最基本的控件,我们必须对button的每个常用属性都熟练应用: 1,使用之前,必须对按钮进行定义,为乐规范,在@interface ViewController (){}中进行定义,先定义后使用. ...

  8. PHP学习笔记(八)

    关于PHP中的缓存函数ob_start() and ob_end_flush(). PHP输出机制:输出内容->缓存->输出到浏览器.ob_start(callback function) ...

  9. OpenGL_Qt学习笔记之_05(纹理映射)(转)

    转自:http://www.cnblogs.com/tornadomeet/archive/2012/08/24/2654719.html 纹理映射基础知识 什么叫纹理映射,一开始我也不明白,感觉这个 ...

  10. 切割TOMCAT日志

    tomcat的catalina.out日志如果不做操作的话,日志就会日积月累的不断增加.我刚入职的时候发现某台服务器的硬盘报警,排查之后我慌了,一个tomcat的日志居然有100G,这怎么可以,在网上 ...