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
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输入解释:
跟题中例子相同
Sample Output
3
6
输出解释:
跟题中例子相同
解题思路:
先建出来最短路树(题目都提示到这个份上了)
然后考虑不走最后一条边那么就要从子节点走或者从一些其他非树边走。
可以证明最后只经过一条非树边
考虑非树边可以怎么走。
一条非树边可以造成的贡献就是其Lca到这两个点上的所有树边。
其答案就是ansx=disu+disv+lenu-v-disx
disx一定那么可以将disu+disv+lenu-v插入树链
最后求最小值就好了。
可以用树链剖分实现。
代码:
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int N=;
int tr[N<<];
struct pnt{
int hd;
int no;
int fa;
int tp;
int dp;
int dis;
int ind;
int wgt;
int mxs;
bool vis;
bool friend operator < (pnt x,pnt y)
{
return x.dis>y.dis;
}
}p[N];
struct ent{
int twd;
int lst;
int vls;
bool use;
}e[N<<];
std::priority_queue<pnt>Q;
/*class priority_queue{
public:
void push(pnt x)
{
line[++siz]=x;
int nw=siz;
while((nw>>1))
{
int nx=nw>>1;
if(line[nx].dis<line[nw].dis)
break;
std::swap(line[nw],line[nx]);
nw=nx;
}
return ;
}
void pop(void)
{
line[1]=line[siz--];
int nw=1;
while((nw<<1)<=siz)
{
int nx=nw<<1;
if(nx<siz&&line[nx].dis>line[nx+1].dis)
nx++;
if(line[nw].dis<line[nx].dis)
break;
std::swap(line[nw],line[nx]);
nw=nx;
}
return ;
}
int top(void)
{
return line[1].no;
}
bool empty(void)
{
return siz==0;
}
private:
pnt line[N];
int siz;
}Q;*/
int n,m;
int cnt;
int dfn;
void ade(int f,int t,int v)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
e[cnt].vls=v;
p[f].hd=cnt;
return ;
}
void Dij(int x)
{
for(int i=;i<=n;i++)
{
p[i].no=i;
p[i].dis=0x3f3f3f3f;
}
p[].dis=;
p[].fa=;
Q.push(p[x]);
while(!Q.empty())
{
x=Q.top().no;
Q.pop();
if(p[x].vis)
continue;
p[x].vis=true;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].dis>p[x].dis+e[i].vls)
{
p[to].fa=x;
p[to].dis=p[x].dis+e[i].vls;
Q.push(p[to]);
}
}
}
return ;
}
void Basic_dfs(int x,int f)
{
p[x].dp=p[f].dp+;
p[x].wgt=;
int maxs=-;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].fa!=x||to==f)
{
e[i].use=true;
continue;
}
Basic_dfs(to,x);
p[x].wgt+=p[to].wgt;
if(maxs<p[to].wgt)
{
p[x].mxs=to;
maxs=p[to].wgt;
}
}
return ;
}
void Build_dfs(int x,int top)
{
if(!x)
return ;
p[x].tp=top;
p[x].ind=++dfn;
Build_dfs(p[x].mxs,top);
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].fa!=x||p[to].ind)
continue;
Build_dfs(to,to);
}
return ;
}
int Lca(int x,int y)
{
while(p[x].tp!=p[y].tp)
{
if(p[p[x].tp].dp<p[p[y].tp].dp)
std::swap(x,y);
x=p[p[x].tp].fa;
}
if(p[x].dp>p[y].dp)
std::swap(x,y);
return x;
}
void update(int l,int r,int ll,int rr,int spc,int v)
{
if(l>rr||ll>r)
return ;
if(ll<=l&&r<=rr)
{
tr[spc]=std::min(tr[spc],v);
return ;
}
int mid=(l+r)>>;
update(l,mid,ll,rr,spc<<,v);
update(mid+,r,ll,rr,spc<<|,v);
return ;
}
int query(int l,int r,int pos,int spc)
{
if(l==r)
return tr[spc];
int ans=tr[spc];
int mid=(l+r)>>;
if(pos<=mid)
return std::min(query(l,mid,pos,spc<<),ans);
else
return std::min(query(mid+,r,pos,spc<<|),ans);
}
int main()
{
memset(tr,0x6f,sizeof(tr));
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
ade(a,b,c);
ade(b,a,c);
}
Dij();
Basic_dfs(,);
Build_dfs(,);
for(int i=;i<=cnt;i+=)
{
int x,y;
x=e[i].twd;
y=e[i+].twd;
int val=e[i].vls+p[x].dis+p[y].dis;
int z=Lca(x,y);
if(e[i].use)
{
while(p[x].tp!=p[z].tp)
{
update(,dfn,p[p[x].tp].ind,p[x].ind,,val);
x=p[p[x].tp].fa;
}
if(x!=z)
update(,dfn,p[z].ind+,p[x].ind,,val);
}
if(e[i+].use)
{
while(p[y].tp!=p[z].tp)
{
update(,dfn,p[p[y].tp].ind,p[y].ind,,val);
y=p[p[y].tp].fa;
}
if(y!=z)
update(,dfn,p[z].ind+,p[y].ind,,val);
}
}
for(int i=;i<=n;i++)
{
int ans=0x3f3f3f3f;
ans=std::min(ans,query(,dfn,p[i].ind,)-p[i].dis);
if(ans==0x3f3f3f3f)
ans=-;
printf("%d\n",ans);
}
return ;
}
BZOJ1576: [Usaco2009 Jan]安全路经Travel(树链剖分)的更多相关文章
- bzoj 1576: [Usaco2009 Jan]安全路经Travel 树链剖分
1576: [Usaco2009 Jan]安全路经Travel Time Limit: 10 Sec Memory Limit: 64 MB Submit: 665 Solved: 227[Sub ...
- 【思维题 并查集 图论】bzoj1576: [Usaco2009 Jan]安全路经Travel
有趣的思考题 Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第 ...
- [BZOJ1576] [Usaco2009 Jan]安全路经Travel(堆优化dijk + (并查集 || 树剖))
传送门 蒟蒻我原本还想着跑两边spfa,发现不行,就gg了. 首先这道题卡spfa,所以需要用堆优化的dijkstra求出最短路径 因为题目中说了,保证最短路径有且只有一条,所以可以通过dfs求出最短 ...
- BZOJ1576 [Usaco2009 Jan]安全路经Travel
首先用Dijkstra做出最短路生成树,设dis[p]为1到p点的最短路长度 对于一条不在生成树上的边u -> v,不妨设fa为u.v的lca 则一fa到v的路径上的任意点x都可以由u达到,走的 ...
- BZOJ1576: [Usaco2009 Jan]安全路经Travel(最短路 并查集)
题意 给你一张无向图,保证从1号点到每个点的最短路唯一.对于每个点求出删掉号点到它的最短路上的最后一条边(就是这条路径上与他自己相连的那条边)后1号点到它的最短路的长度 Sol emmm,考场上想了个 ...
- 【BZOJ1576】[Usaco2009 Jan]安全路经Travel 最短路+并查集
[BZOJ1576][Usaco2009 Jan]安全路经Travel Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, ...
- [BZOJ1576] [BZOJ3694] [USACO2009Jan] 安全路径(最短路径+树链剖分)
[BZOJ1576] [BZOJ3694] [USACO2009Jan] 安全路径(最短路径+树链剖分) 题面 BZOJ1576和BZOJ3694几乎一模一样,只是BZOJ3694直接给出了最短路树 ...
- bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)
[题意] 给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠. [思路] 首先用dijkstra算法构造以1为根的最短路树. 将一条无向边看作两条有向边,考察一条不在最短路树上 ...
- [BZOJ 1576] [Usaco2009 Jan] 安全路经Travel 【树链剖分】
题目链接: BZOJ - 1576 题目分析 首先Orz Hzwer的题解. 先使用 dijikstra 求出最短路径树. 那么对于一条不在最短路径树上的边 (u -> v, w) 我们可以先沿 ...
随机推荐
- BZOJ2895: 球队预算
[传送门:BZOJ2895] 简要题意: 在一个篮球联赛里,有n支球队,球队的支出是和他们的胜负场次有关系的,具体来说,第i支球队的赛季总支出是Ci*x^2+Di*y^2,Di<=Ci.(赢得多 ...
- Android 5.0(Lollipop)中的SurfaceTexture,TextureView, SurfaceView和GLSurfaceView
SurfaceView, GLSurfaceView, SurfaceTexture以及TextureView是Android当中名字比较绕,关系又比较密切的几个类.本文基于Android 5.0(L ...
- zzulioj--1801--xue姐的小动物(水题)
1801: xue姐的小动物 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 594 Solved: 168 SubmitStatusWeb Boar ...
- Github-flavored Markdown 导出为 PDF
前提条件: 你可以访问Google和它相关的服务 第一步 到Chrome Store安装插件 Markdown Preview Plus 安装以后记得勾选 "允许访问文件网址" 设 ...
- HDU 4372 Count the Buildings
Count the Buildings Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- 分享一段官date函数用法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- POJ 1610 Count the Colors
Count the Colors Time Limit: 2 Seconds Memory Limit: 65536 KB Painting some colored segments on ...
- UESTC 1599 wtmsb
这天,AutSky_JadeK看到了n张图片,他忍不住说道:“我TM社保!”. 每张图片有一个社保值,他可以合并两张图片,合并所得的图片的社保值是原来两张图片的社保值之和. 每次合并需要消耗的体力也是 ...
- I want to do——输入流readline阻塞问题
据悉,外界对程序员的印象不是木讷就是死板,不是最笨就是不爱说话,不是宅就是闷骚.昨天我们老左批评我说,自从你写了程序了,你以前的优点都退化了.放在去年,我还觉得我没什么啊,程序员就是这样啊,那是因为我 ...
- python单元测试-unittest
python内部自带了一个单元测试的模块,pyUnit也就是我们说的:unittest 1.介绍下unittest的基本使用方法: 1)import unittest 2)定义一个继承自unittes ...