BZOJ1576: [Usaco2009 Jan]安全路经Travel(树链剖分)
Description
.jpg)
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) 我们可以先沿 ...
随机推荐
- 由安装两块网卡的linux系统中引起网络不通想到的
由安装两块网卡的linux系统中引起网络不通想到的 一天,小王突然急匆匆的来找我,他说:"我在机子上刚装的redhat怎么老也ping不通服务器,我网卡的驱动都安装了,ping 自己的两块网 ...
- Aspose.Cells相应操作及下载
Aspose.Cells相应操作 1,上传 1.1 Workbook Workbook workBook = new Workbook(); 属性: 名称 值类型 说明 Colors Color[] ...
- HTML5新增的一些特性
HTML现在已经不是SGML的子集,主要是关于图像,位置,储存,多任务等功能的增加. .绘画canvas: .用于媒介回放的video: Ogg是带有Theora视频编码和Vorbis音频编码的文件: ...
- su su- sudo区别概述
在Linux的操作中经常会用到su 命令进行用户的切换和sudo命令获取root权限,su su- sudo三个命令经常弄混,下面简单的讲解下. 一.查看su的命令帮助信息: pipci@openSU ...
- 在使用FireFox浏览器时,经常打开新标签,页面总是不断自动刷新,解决办法
可以用如下方法尝试(逐个尝试,看看哪个管用): 1.地址栏输入 about:support,右上角有个翻新Firefox,点击,等待浏览器重启,即可. 2.点击:工具-附加组件,把“火狐主页和标签管理 ...
- 学习《零基础入门学习Python》电子书PDF+笔记+课后题及答案
初学python入门建议学习<零基础入门学习Python>.适合新手入门,很简单很易懂.前一半将语法,后一半讲了实际的应用. Python3入门必备,小甲鱼手把手教授Python,包含电子 ...
- mysql索引工作原理、分类
一.概述 在mysql中,索引(index)又叫键(key),它是存储引擎用于快速找到所需记录的一种数据结构.在越来越大的表中,索引是对查询性能优化最有效的手段,索引对性能影响非常关键.另外,mysq ...
- 直接修改Android软件数据库来改变软件设置实例一则
昨天把K860i刷了机,刷到了最新的CyanogenMod 10.1,使用起来各种流畅舒服,不过却由于内外置SD卡的挂载点的改变,造成了一些困扰,现记录如下. 平时里由于极少把手机连接 ...
- tee---将数据重定向到文件,
tee命令用于将数据重定向到文件,另一方面还可以提供一份重定向数据的副本作为后续命令的stdin.简单的说就是把数据重定向到给定文件和屏幕上. 存在缓存机制,每1024个字节将输出一次.若从管道接收输 ...
- CCF模拟题 有趣的数
有趣的数 时间限制: 1.0s 内存限制: 256.0MB 问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都 ...