【BZOJ】1602:[Usaco2008 Oct]牧场行走
【算法】最近公共祖先(LCA)
【题解】
点x,y到最近公共祖先z的距离之和相当于x,y到根的距离减去两倍z到根的距离,
即ans=dis[x]+dis[y]-2*dis[z]
记得边数组要开两倍!!!T_T
#include<cstdio>
#include<algorithm>
using namespace std;
const double eps=1e-;
const int maxn=;
struct cyc{int from,to,w;}e[maxn*];
int dis[maxn],deep[maxn],f[maxn][],n,q,cnt,head[maxn];
bool vis[maxn];
void insert(int u,int v,int w)
{cnt++;e[cnt].from=head[u];e[cnt].to=v;e[cnt].w=w;head[u]=cnt;}
void dfs(int x)
{
vis[x]=;
for(int i=;(<<i)<=deep[x];i++)
f[x][i]=f[f[x][i-]][i-];
for(int i=head[x];i;i=e[i].from)
if(!vis[e[i].to])
{
int now=e[i].to;
deep[now]=deep[x]+;
dis[now]=dis[x]+e[i].w;
f[now][]=x;
dfs(now);
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int d=deep[x]-deep[y];
for(int i=;(<<i)<=d;i++)
if((<<i)&d)x=f[x][i];
if(x==y)return x;
for(int i=;i>=;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][];
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);
insert(v,u,w);
}
dfs();
for(int i=;i<=q;i++)
{
int p1,p2;
scanf("%d%d",&p1,&p2);
printf("%d\n",dis[p1]+dis[p2]-*dis[lca(p1,p2)]);
}
return ;
}
也可以记录g[x][i],则不必减去多余的。
事实证明在一些简单的树上路径问题上,倍增比链剖更有优势。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
struct edge{int v,from,w;}e[maxn*];
int n,first[maxn],deep[maxn],f[maxn][],g[maxn][],v[maxn],tot,lca,q;
void insert(int u,int v,int w)
{tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
void dfs(int x,int fa)
{
for(int i=;(<<i)<=deep[x];i++)
{
f[x][i]=f[f[x][i-]][i-];
g[x][i]=g[x][i-]+g[f[x][i-]][i-];
}
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa)
{
int y=e[i].v;
f[y][]=x;
deep[y]=deep[x]+;
g[y][]=e[i].w;
dfs(y,x);
}
}
int find(int x,int y)
{
int ans=;
if(deep[x]<deep[y])swap(x,y);
int d=deep[x]-deep[y];
for(int i=;(<<i)<=deep[x];i++)
if((<<i)&d){ans+=g[x][i];x=f[x][i];}
if(x==y)return ans;
for(int i=;i>=;i--)
if((<<i)<=deep[x]&&f[x][i]!=f[y][i])
{
ans+=g[x][i]+g[y][i];
x=f[x][i];y=f[y][i];
}
lca=f[x][];
return ans+g[x][]+g[y][];
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);
insert(v,u,w);
}
dfs(,-);
for(int i=;i<=q;i++)
{
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",find(u,v));
}
return ;
}
【BZOJ】1602:[Usaco2008 Oct]牧场行走的更多相关文章
- bzoj 1602 [Usaco2008 Oct]牧场行走(LCA模板)
1602: [Usaco2008 Oct]牧场行走 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 379 Solved: 216[Submit][Sta ...
- BZOJ 1602: [Usaco2008 Oct]牧场行走( 最短路 )
一棵树..或许用LCA比较好吧...但是我懒...写了个dijkstra也过了.. ---------------------------------------------------------- ...
- BZOJ——1602: [Usaco2008 Oct]牧场行走 || 洛谷—— P2912 [USACO08OCT]牧场散步Pasture Walking
http://www.lydsy.com/JudgeOnline/problem.php?id=1602 || https://www.luogu.org/problem/show?pid=2912 ...
- BZOJ 1602: [Usaco2008 Oct]牧场行走 倍增裸题
Description N头牛(2<=n<=1000)别人被标记为1到n,在同样被标记1到n的n块土地上吃草,第i头牛在第i块牧场吃草. 这n块土地被n-1条边连接. 奶牛可以在边上行走, ...
- LCA || BZOJ 1602: [Usaco2008 Oct]牧场行走 || Luogu P2912 [USACO08OCT]牧场散步Pasture Walking
题面:[USACO08OCT]牧场散步Pasture Walking 题解:LCA模版题 代码: #include<cstdio> #include<cstring> #inc ...
- BZOJ 1602 [Usaco2008 Oct]牧场行走 dfs
题意:id=1602">链接 方法:深搜暴力 解析: 这题刚看完还有点意思,没看范围前想了想树形DP,只是随便画个图看出来是没法DP的,所以去看范围. woc我没看错范围?果断n^2暴 ...
- BZOJ 1602 USACO2008 Oct 牧场行走
翻翻吴大神的刷题记录翻到的... 乍一看是一个树链剖分吓瓜我...难不成吴大神14-10-28就会了树剖?orz... 再一看SB暴力都可过... 然后一看直接树上倍增码个就好了... 人生真是充满着 ...
- bzoj 1602: [Usaco2008 Oct]牧场行走【瞎搞】
本来想爆手速写个树剖,然而快下课了就手残写了了个n方的短小-- 暴力把查询的两个点中深的一个跳上来,加上边权,然后一起跳加边权就行了 #include<iostream> #include ...
- 1602: [Usaco2008 Oct]牧场行走
1602: [Usaco2008 Oct]牧场行走 Time Limit: 5 Sec Memory Limit: 64 MB Submit: 1211 Solved: 616 [Submit][ ...
- 【BZOJ】1602: [Usaco2008 Oct]牧场行走(lca)
http://www.lydsy.com/JudgeOnline/problem.php?id=1602 一开始以为直接暴力最短路,但是n<=1000, q<=1000可能会tle. 显然 ...
随机推荐
- lintcode-153-数字组合 II
153-数字组合 II 给出一组候选数字(C)和目标数字(T),找出C中所有的组合,使组合中数字的和为T.C中每个数字在每个组合中只能使用一次. 注意事项 所有的数字(包括目标数字)均为正整数. 元素 ...
- Python 零碎信息-基础 01
1. """ 可以插入多行文字. print """ abC 123' 456''" #单引号, 双引号, 也没有关系 " ...
- Mysql查询优化从入门到跑路(三)查询的基本操作
查询的基本操作 1.选择操作 对应的是限制条件,操作对象是二维表的行. 优化方式:选择操作下推 目的:尽量减少连接操作前的元租数,使得中间临时关系尽量少(元祖数少,连接得到的元组数就少 ...
- 如何用grep命令同时显示匹配行上下的n行 (美团面试题目)
标准unix/linux下的grep通过以下参数控制上下文 grep -C 5 foo file 显示file文件中匹配foo字串那行以及上下5行grep -B 5 foo file 显示foo及前5 ...
- 【python】python字符串前面加u,r,b的含义
1.字符串前加 u 例:u"我是含有中文字符组成的字符串." 作用:后面字符串以 Unicode 格式 进行编码,一般用在中文字符串前面,防止因为源码储存格式问题,导致再次使用时出 ...
- iOS开发UI篇—transframe属性(形变)
iOS开发UI篇—transframe属性(形变) 1. transform属性 在OC中,通过transform属性可以修改对象的平移.缩放比例和旋转角度 常用的创建transform结构体方法分两 ...
- BZOJ 1211 树的计数(purfer序列)
首先考虑无解的情况, 根据purfer序列,当dee[i]=0并且n!=1的时候,必然无解.否则为1. 且sum(dee[i]-1)!=n-2也必然无解. 剩下的使用排列组合即可推出公式.需要注意的是 ...
- 【bzoj1212】[HNOI2004]L语言 AC自动机
题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的 ...
- 关于"作数类型冲突: nvarchar 与 image 不兼容"的问题
数据库如果是Image类型,当执行插入语句时,如果插入的值是DBNull.Value时提示:操作数类型冲突: nvarchar 与 image 不兼容; 出现这个问题的原因是没有指定DbType的原因 ...
- P1278 单词游戏
题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...