【BZOJ1576】[Usaco2009 Jan]安全路经Travel

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
输出解释:
跟题中例子相同

题解: 先求出最短路径树,然后我们统计每条非树边对每个点的影响。一条非树边可以更新它覆盖的所有点,如果这条边(x,y,len)覆盖了z,那么ans[z]=min(ans[z],dis[x]+dis[y]+len-dis[z]),因为dis[z]是确定的,所以我们维护链上的dis[x]+dis[y]+len的最小值即可。

如何维护?树剖+线段树,倍增,都是不错的方案,当然有更巧的。将所有非树边按dis[x]+dis[y]+len从小到大排序,然后用并查集维护所有没被更新的点,暴力更新路径上没被更新的点即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <utility>
#define mp(A,B) make_pair(A,B)
using namespace std;
const int maxn=100010;
int n,m,cnt;
int to[maxn<<2],next[maxn<<2],val[maxn<<2],head[maxn],dis[maxn],fa[maxn],pre[maxn];
int f[maxn],s[maxn],ans[maxn];
bool vis[maxn];
priority_queue<pair<int,int> > q;
struct edge
{
int a,b,v;
bool ont;
}p[maxn<<1];
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd()
{
int ret=0,f=1; char gc=nc();
while(!isdigit(gc)) {if(gc=='-') f=-f; gc=nc();}
while(isdigit(gc)) ret=ret*10+gc-'0',gc=nc();
return ret*f;
}
inline void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
bool cmp(const edge &a,const edge &b)
{
return a.v<b.v;
}
int find(int x)
{
return (f[x]==x)?x:(f[x]=find(f[x]));
}
int main()
{
n=rd(),m=rd();
memset(head,-1,sizeof(head));
register int i,u,a,b;
for(i=1;i<=m;i++) p[i].a=rd(),p[i].b=rd(),p[i].v=rd(),add(p[i].a,p[i].b,p[i].v),add(p[i].b,p[i].a,p[i].v);
memset(dis,0x3f,sizeof(dis));
dis[1]=0,q.push(mp(0,1));
while(!q.empty())
{
u=q.top().second,q.pop();
if(vis[u]) continue;
vis[u]=1;
for(i=head[u];i!=-1;i=next[i]) if(dis[to[i]]>dis[u]+val[i])
fa[to[i]]=u,pre[to[i]]=(i>>1)+1,dis[to[i]]=dis[u]+val[i],q.push(mp(-dis[to[i]],to[i]));
}
for(i=1;i<=n;i++) f[i]=i,p[pre[i]].ont=1;
for(i=1;i<=m;i++) p[i].v+=dis[p[i].a]+dis[p[i].b];
sort(p+1,p+m+1,cmp);
for(i=1;i<=m;i++) if(!p[i].ont)
{
a=find(p[i].a),b=find(p[i].b);
while(a!=b)
{
if(dis[a]<dis[b]) swap(a,b);
ans[a]=p[i].v-dis[a],f[a]=fa[a],a=find(f[a]);
}
}
for(i=2;i<=n;i++) printf("%d\n",(!ans[i])?-1:ans[i]);
return 0;
}

【BZOJ1576】[Usaco2009 Jan]安全路经Travel 最短路+并查集的更多相关文章

  1. BZOJ1576: [Usaco2009 Jan]安全路经Travel(最短路 并查集)

    题意 给你一张无向图,保证从1号点到每个点的最短路唯一.对于每个点求出删掉号点到它的最短路上的最后一条边(就是这条路径上与他自己相连的那条边)后1号点到它的最短路的长度 Sol emmm,考场上想了个 ...

  2. 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的距离 ...

  3. 【思维题 并查集 图论】bzoj1576: [Usaco2009 Jan]安全路经Travel

    有趣的思考题 Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第 ...

  4. BZOJ1576 [Usaco2009 Jan]安全路经Travel

    首先用Dijkstra做出最短路生成树,设dis[p]为1到p点的最短路长度 对于一条不在生成树上的边u -> v,不妨设fa为u.v的lca 则一fa到v的路径上的任意点x都可以由u达到,走的 ...

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

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

  6. [BZOJ1576] [Usaco2009 Jan]安全路经Travel(堆优化dijk + (并查集 || 树剖))

    传送门 蒟蒻我原本还想着跑两边spfa,发现不行,就gg了. 首先这道题卡spfa,所以需要用堆优化的dijkstra求出最短路径 因为题目中说了,保证最短路径有且只有一条,所以可以通过dfs求出最短 ...

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

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

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

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

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

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

随机推荐

  1. Js日常笔记之this

    在javascript中自己创建构造函数时可以利用this来指向新创建的对象上.这样就可以避免函数中的this指向全局了,如下 var x = 2; function test(){ this.x = ...

  2. STL容器分析--set

    STL 对这个序列可以进行查找,插入删除序列中的任意一个元素,而完成这些操作的时间同这个序列中元素个数的对数成比例关系,并且当游标指向一个已删除的元素时,删除操作无效.而一个经过更正的和更加实际的定义 ...

  3. 又开一坑,运动图形MoGraph for Unity

    Fragment+random: Vertex+random, Vertex+plain Vertex+Sound Plexus like 写了个大概,暂时没这方面需求先放这边了. C4D原版片段和克 ...

  4. makefile之findstring函数

    #$(findstring <find>,<in> ) #功能:在字串<in>中查找<find>字串. #返回:如果找到,那么返回<find> ...

  5. 架设HmailServer邮件服务器以及webmail

    参考:http://www.it0355.com/a/201207/31/a9275.htm 在安裝Hmailserver前先安裝Apache.php.mysql,如果你想懶點直接到http://ww ...

  6. 个人的Linux实用命令

    Linux下的命令有那么多,我不可能也不想去把每一个都记住,列举一些自己工作中很实用的命令,这些命令或许不是很常用,但是有时候却离不了. 1.网络方面 service iptables start/s ...

  7. [转]C++11 标准新特性:Defaulted 和 Deleted 函数

    http://www.ibm.com/developerworks/cn/aix/library/1212_lufang_c11new/

  8. IPC之信号量

    无名信号量 POSIX标准提出了有名信号量和无名信号量来同步进程和线程,而linux(2.6以前)只实现了无名信号量. sem_overview中有详细介绍:man 7 sem_overview. S ...

  9. Linux高频指令总结

    作为一个计算机专业的科班,不会玩Linux怎么能行呢?玩Linux用可视化界面显得太low了,为了效(zhuang)率(bi),当然要用什么都用指令啊,可是指令太多了啊,现在就把平时遇到的高频的指令做 ...

  10. Make Docker Image On Ubuntu17.10

    1.拉取基础镜像 docker pull ubuntu 2.查看镜像 docker images 3.启动一个容器 docker run -it ubuntu 4.查找运行的容器ID docker p ...