Description

  小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上。有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力。
  已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力

Input

  第一行一个n,接下来n-1行每一行有三个整数u,v, c 。表示节点 u 爬到节点 v 需要花费 c 的精力。
  第n+1行有一个整数m表示有m次询问。接下来m行每一行有两个整数 u ,v 表示两只虫子所在的节点

Output

  一共有m行,每一行一个整数,表示对于该次询问所得出的最短距离。

Sample Input

3
1 0 1
2 0 1
3
1 0
2 0
1 2

Sample Output

1
1
2

HINT

  1<=n<=50000, 1<=m<=75000, 0<=c<=1000

Source

Solution

  倍增求LCA, $O((n + m)logn)$

 #include <bits/stdc++.h>
using namespace std;
struct edge
{
int v, w, nxt;
}e[];
int fst[], q[], front, back;
int fa[][], dis[], dep[]; void addedge(int i, int u, int v, int w)
{
e[i] = (edge){v, w, fst[u]}, fst[u] = i;
} int LCA(int u, int v)
{
if(dep[u] > dep[v]) swap(u, v);
for(int i = ; ~i; i--)
if(dep[fa[i][v]] >= dep[u])
v = fa[i][v];
if(u == v) return u;
for(int i = ; ~i; i--)
if(fa[i][u] != fa[i][v])
u = fa[i][u], v = fa[i][v];
return fa[][u];
} int main()
{
int n, m, u, v, w;
cin >> n;
for(int i = ; i < n; i++)
{
cin >> u >> v >> w;
addedge(i << , ++u, ++v, w);
addedge(i << | , v, u, w);
}
q[++back] = , dep[] = fa[][] = ;
while(front != back)
{
u = q[++front];
for(int i = fst[u]; i; i = e[i].nxt)
if(e[i].v != fa[][u])
{
q[++back] = e[i].v;
dep[e[i].v] = dep[u] + ;
fa[][e[i].v] = u;
dis[e[i].v] = dis[u] + e[i].w;
}
}
for(int i = ; i <= ; i++)
for(int j = ; j <= n; j++)
fa[i][j] = fa[i - ][fa[i - ][j]];
cin >> m;
while(m--)
{
cin >> u >> v, u++, v++;
cout << dis[u] + dis[v] - * dis[LCA(u, v)] << endl;
}
return ;
}

  Tarjan求LCA, $O(n + m)$(写法较鬼畜)

 #include <bits/stdc++.h>
using namespace std;
struct edge
{
int v, w, nxt;
}e[];
struct query
{
int u, v, nxt;
}q[];
int efst[], qfst[], fa[], lca[], dis[];
bool vis[]; void addedge(int i, int u, int v, int w)
{
e[i] = (edge){v, w, efst[u]}, efst[u] = i;
} void addquery(int i, int u, int v)
{
q[i] = (query){u, v, qfst[u]}, qfst[u] = i;
} int get_dis(int i)
{
return dis[q[i << ].u] + dis[q[i << ].v] - * dis[lca[i]];
} int getfa(int x)
{
return fa[x] = x == fa[x] ? x : getfa(fa[x]);
} void Tarjan(int u)
{
fa[u] = u, vis[u] = true;
for(int i = efst[u]; i; i = e[i].nxt)
if(!vis[e[i].v])
{
dis[e[i].v] = dis[u] + e[i].w;
Tarjan(e[i].v);
fa[e[i].v] = u;
}
for(int i = qfst[u]; i; i = q[i].nxt)
{
int v = q[i].u == u ? q[i].v : q[i].u;
if(vis[v]) lca[i >> ] = getfa(fa[v]);
}
} int main()
{
int n, m, u, v, w;
cin >> n;
for(int i = ; i < n; i++)
{
cin >> u >> v >> w;
addedge(i << , ++u, ++v, w);
addedge(i << | , v, u, w);
}
cin >> m;
for(int i = ; i <= m; i++)
{
cin >> u >> v;
addquery(i << , ++u, ++v);
addquery(i << | , v, u);
}
Tarjan();
for(int i = ; i <= m; i++)
cout << get_dis(i) << endl;
return ;
}

  树链剖分求LCA, $O(mlogn)$,我习惯把树剖维护的7个信息写到结构体里。

 #include <bits/stdc++.h>
using namespace std;
struct edge
{
int v, w, nxt;
}e[];
struct point
{
int fa, siz, son, dep, dis, dfn, top;
}p[];
int ptot, fst[]; void addedge(int i, int u, int v, int w)
{
e[i] = (edge){v, w, fst[u]}, fst[u] = i;
} void DFS1(int u)
{
p[u].siz = ;
for(int i = fst[u]; i; i = e[i].nxt)
if(e[i].v != p[u].fa)
{
p[e[i].v].fa = u;
p[e[i].v].dep = p[u].dep + ;
p[e[i].v].dis = p[u].dis + e[i].w;
DFS1(e[i].v);
p[u].siz += p[e[i].v].siz;
if(p[e[i].v].siz > p[p[u].son].siz)
p[u].son = e[i].v;
}
} void DFS2(int u, int top)
{
p[u].dfn = ++ptot, p[u].top = top;
if(p[u].son) DFS2(p[u].son, top);
for(int i = fst[u]; i; i = e[i].nxt)
if(e[i].v != p[u].fa && e[i].v != p[u].son)
DFS2(e[i].v, e[i].v);
} int LCA(int u, int v)
{
while(p[u].top != p[v].top)
{
if(p[p[u].top].dep > p[p[v].top].dep) swap(u, v);
v = p[p[v].top].fa;
}
if(p[u].dep > p[v].dep) swap(u, v);
return u;
} int main()
{
int n, m, u, v, w;
cin >> n;
for(int i = ; i < n; i++)
{
cin >> u >> v >> w;
addedge(i << , ++u, ++v, w);
addedge(i << | , v, u, w);
}
p[].dep = , DFS1(), DFS2(, );
cin >> m;
while(m--)
{
cin >> u >> v, u++, v++;
cout << p[u].dis + p[v].dis - * p[LCA(u, v)].dis << endl;
}
return ;
}

  LCT, $O(mlog^{2}n)$

 #include <bits/stdc++.h>
using namespace std;
struct LCT
{
int fa, c[], rev, key, sum;
int& operator [] (int i)
{
return c[i];
}
}a[];
int sta[], top; void push_up(int k)
{
a[k].sum = a[a[k][]].sum + a[a[k][]].sum + a[k].key;
} void push_down(int k)
{
if(a[k].rev)
{
a[a[k][]].rev ^= , a[a[k][]].rev ^= ;
swap(a[k][], a[k][]), a[k].rev = ;
}
} bool isroot(int x)
{
return a[a[x].fa][] != x && a[a[x].fa][] != x;
} void rotate(int x)
{
int y = a[x].fa, z = a[y].fa;
int dy = a[y][] == x, dz = a[z][] == y;
if(!isroot(y)) a[z][dz] = x;
a[y][dy] = a[x][dy ^ ], a[a[x][dy ^ ]].fa = y;
a[x][dy ^ ] = y, a[y].fa = x, a[x].fa = z;
push_up(y);
} void splay(int x)
{
sta[top = ] = x;
for(int i = x; !isroot(i); i = a[i].fa)
sta[++top] = a[i].fa;
while(top)
push_down(sta[top--]);
while(!isroot(x))
{
int y = a[x].fa, z = a[y].fa;
if(!isroot(y))
if(a[y][] == x ^ a[z][] == y) rotate(x);
else rotate(y);
rotate(x);
}
push_up(x);
} void access(int x)
{
for(int i = ; x; x = a[x].fa)
splay(x), a[x][] = i, i = x;
} void make_root(int x)
{
access(x), splay(x), a[x].rev ^= ;
} void link(int x, int y)
{
make_root(x), a[x].fa = y;
} void cut(int x, int y)
{
make_root(x), access(y), splay(y), a[y][] = a[x].fa = ;
} int find_root(int x)
{
access(x), splay(x);
while(a[x][])
x = a[x][];
return x;
} int main()
{
int n, m, u, v, w;
cin >> n;
for(int i = ; i < n; i++)
{
cin >> u >> v >> w;
a[i + n].sum = a[i + n].key = w;
link(++u, i + n), link(i + n, ++v);
}
cin >> m;
while(m--)
{
cin >> u >> v;
make_root(++u), access(++v), splay(v);
printf("%d\n", a[v].sum);
}
return ;
}

[CodeVS2370] 小机房的树 (LCA, 树链剖分, LCT)的更多相关文章

  1. Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式)

    Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)↗[GO!] 题意 是说有棵树,每个节点上 ...

  2. codevs2370 小机房的树 x

    2370 小机房的树  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond   题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号 ...

  3. codevs2370 小机房的树

    题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子, ...

  4. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5020  Solved: 1872[Submit][Status ...

  5. Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 11102  Solved: 4490[Submit ...

  6. [FJOI2014]最短路径树问题 长链剖分

    [FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...

  7. BZOJ2243: [SDOI2011]染色(树链剖分/LCT)

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...

  8. 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分/LCT+贪心

    Description 给你一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示. 每次询问包含三个数x,y,z,初始选定一个数v.然后v依 ...

  9. [codevs2370]小机房的树<LCA>

    题目链接:http://codevs.cn/problem/2370/ 这题我还是做了比较久了,因为有人告诉我这是用tarjan离线做 好吧算我是蒟蒻,真心不懂tarjan怎么做,最后还是用倍增做的 ...

随机推荐

  1. C控制语句:分支和跳转

    小技巧:程序return前加个getchar();可以让程序停住.%%可以打印使printf()中打印出%号 #include<stdio.h>#define SPACE ''int ma ...

  2. golang 实现简单的一致性哈希

    package main import ( "fmt" "sort" "hash/crc32" ) var serverMap map[ui ...

  3. HTML/CSS 知识点

    整个前端开发的工作流程 产品经理提出项目需求 UI出设计稿 前端人员负责开发静态页面(跟前端同步的后台人员在准备数据) 前后台的交互 测试 产品上线(后期项目维护) 互联网原理 当用户在浏览器输入网址 ...

  4. 【学习笔记】Hibernate 一对一关联映射 组件映射 二级缓存 集合缓存

    啊讲道理放假这十天不到啊 感觉生活中充满了绝望 这就又开学了 好吧好吧继续学习笔记?还是什么的 一对一关联映射 这次我们仍然准备了两个表 一个是用户表Users 一个是档案表Resume 他们的关系是 ...

  5. DB2物化视图——MQT 物化查询表的正确使用(materialized query tables)

    我们今天主要向大家讲述的是DB2物化视图——MQT 物化查询表使用,以下就是对DB2物化视图之MQT物化查询表的正确使用的主要内容的详细描述,望大家在浏览之后会对其有更深的了解. MQT 的定义基于查 ...

  6. GNU autotools自动生成Makefile 介绍

    一.目的 使用autotools工具来帮助我们自动地生成符合自由软件惯例的makefile(这样就可以像常见的GNU程序一样,只要使用"./configure", "ma ...

  7. Duilib第一步(III)-知识进阶

    核心模块 CWindowWnd:窗口对象管理父类 创建窗口. 窗口消息过程处理. 提供窗口子类化.超类化接口. CDialogBuilder:空间布局类 解析XML界面布局文件,构建控件树 创建控件对 ...

  8. dubbox系列【四】——使用dubbo-monitor-x监控注册中心

    1.下载源码,编译成war包 源码下载地址为:https://git.oschina.net/yjmyzz/dubbo-monitor.git 在pom.xml文件所在目录,直接执行mvn packa ...

  9. Java中的return关键字

    Java常见面试题之一: try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?  请看下面程序就可以解释 ...

  10. nginx笔记5-双机热备原理

    1动静分离演示: 将笔记3的Demo改造一下,如图所示: 改造完成后,其实就是在网页上显示一张图片 现在启动Tomcat运行起来,如图: 可以看到图片的请求是请求Tomcat下的图片. 现在,通过把静 ...