hihoCoder挑战赛11.题目4 : 高等理论计算机科学(LCA)
clj在某场hihoCoder比赛中的一道题,表示clj的数学题实在6,这道图论貌似还算可以。。。
题目链接:http://hihocoder.com/problemset/problem/1167
由于是中文题目,题意不再赘述。
对于任意两条小精灵的活动路径a和b,二者相交的判断条件为b的两个端点的LCA在a的路径上;那么我们可以首先将每个活动路径端点的LCA离线预处理出来,对每个节点LCA值+1。
然后以某个节点(我选择的是节点1)为根进行深搜,算出一条从节点1到节点x的LCA值和,那么任意路径a(假设其两端点分别是A和B)上的节点个数就是sum[A] + sum[B] - 2 * sum[LCA(A,B)]。
最后,对于某些点,如果它是不止一条路径的LCA,那么我们只需要对最终答案乘以C(LCAnum, 2)的组合数就好。
【PS:clj给出的题解中,采用了点分治+LCA的方式,虽然看懂了题意,但是表示对递归分治之后的路径,如何求出其上的LCAnum,并没有多好的想法,还望巨巨能指点一下,Thx~】
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
#define MAXN 100010
struct Edge {
int to, next;
} edge[MAXN << ];
struct Node {
int to, next, num;
} Query[MAXN << ];
struct node {
int u, v, lca;
} input[MAXN];
int totEdge, totQuery, n, m;
int headEdge[MAXN], headQuery[MAXN];
int ancestor[MAXN], father[MAXN], LCAnum[MAXN], sum[MAXN];
bool vis[MAXN];
void addEdge(int from, int to) {
edge[totEdge].to = to;
edge[totEdge].next = headEdge[from];
headEdge[from] = totEdge++;
}
void addQuery(int from, int to, int x) {
Query[totQuery].to = to;
Query[totQuery].num = x;
Query[totQuery].next = headQuery[from];
headQuery[from] = totQuery++;
}
void init() {
memset(headEdge, -, sizeof(headEdge));
memset(headQuery, -, sizeof(headQuery));
memset(father, -, sizeof(father));
memset(vis, false, sizeof(vis));
memset(sum, , sizeof(sum));
memset(LCAnum, , sizeof(LCAnum));
totEdge = totQuery = ;
}
int find_set(int x) {
if(x == father[x]) return x;
else return father[x] = find_set(father[x]);
}
void union_set(int x, int y) {
x = find_set(x); y = find_set(y);
if(x != y) father[y] = x;
}
void Tarjan(int u) {
father[u] = u;
for(int i = headEdge[u]; i != -; i = edge[i].next) {
int v = edge[i].to;
if(father[v] != -) continue;
Tarjan(v);
union_set(u, v);
}
for(int i = headQuery[u]; i != -; i = Query[i].next) {
int v = Query[i].to;
if(father[v] == -) continue;
input[Query[i].num].lca = find_set(v);
}
}
void DFS(int u, int pre) {
vis[u] = ;
sum[u] = sum[pre] + LCAnum[u];
for(int i = headEdge[u]; i != -; i = edge[i].next) {
int v = edge[i].to;
if(vis[v]) continue;
DFS(v, u);
}
}
int main() {
init();
scanf("%d%d", &n, &m);
for(int i = ; i < n - ; i++) {
int a, b;
scanf("%d%d", &a, &b);
addEdge(a, b); addEdge(b, a);
}
for(int i = ; i < m; i++) {
int a, b;
scanf("%d%d", &a, &b);
input[i].u = a, input[i].v = b;
addQuery(a, b, i); addQuery(b, a, i);
}
Tarjan();
for(int i = ; i < m; i++)
LCAnum[input[i].lca]++;
DFS(, );
LL ans = ;
for(int i = ; i < m; i++) {
ans += (sum[input[i].u] + sum[input[i].v] - * sum[input[i].lca]);
}
for(int i = ; i <= n; i++) {
ans += (LL)LCAnum[i] * (LCAnum[i] - ) / ;
}
printf("%lld\n", ans);
return ;
}
转载:)
hihoCoder挑战赛11.题目4 : 高等理论计算机科学(LCA)的更多相关文章
- 【Hihocoder 1167】 高等理论计算机科学 (树链的交,线段树或树状数组维护区间和)
[题意] 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 少女幽香这几天正在学习高等理论计算机科学,然而她什么也没有学会,非常痛苦.所以她出去晃了一晃,做起了一些没什么意 ...
- [题解]hihoCoder挑战赛18——题目1 神奇字符串
题目地址:http://hihocoder.com/problemset/problem/1264 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 我们说两个字符串是非常 ...
- hihoCoder挑战赛28 题目3 : 树的方差
题目3 : 树的方差 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 对于一棵 n 个点的带标号无根树,设 d[i] 为点 i 的度数. 定义一棵树的方差为数组 d[1. ...
- hihoCoder挑战赛28 题目2 : 二进制翻转
题目2 : 二进制翻转 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 定义函数 Rev(x) 表示把 x 在二进制表示下翻转后的值 例如: Rev(4)=1,因为 4 ...
- hihoCoder挑战赛28 题目1 : 异或排序
题目1 : 异或排序 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个长度为 n 的非负整数序列 a[1..n] 你需要求有多少个非负整数 S 满足以下两个条件: ...
- hihoCoder挑战赛27题目一 福字 (dp)
题目: 一个n × n的矩阵,其中每个位置都是一个非负整数. 一个福字被定义成是大小为 k 的正方形,满足其中的每个位置上的数都恰好比他的左边的那个和上边的那个大1(如果左边或上边的那个不存在的话就无 ...
- hihoCoder挑战赛11 A 随机斐波那契
算了前三项.....发现是个大水题... #include<stdio.h> int main() { int n; while (~scanf("%d", &am ...
- 【hihocoder1167】高等理论计算机科学 (重链剖分 +树状数组)
Descroption 原题链接给你一棵\(~n~\)个点的树和\(~m~\)条链,求两两相交的链有多少对,两条链相交当且仅当有至少一个公共点.\(~1 \leq n, m \leq 10 ^ 5~\ ...
- hihoCoder挑战赛23
hihoCoder挑战赛23 A.Emulator 题意 给一张图,有\(N(N \le 300)\)个点, 给出任意两点之间的最短路. 求最多可以去掉多少条边,使得任意两点的最短路长度不变. 思路 ...
随机推荐
- jQuery基础(1) -- jQuery 语法
通过 jQuery,您可以选取(查询,query) HTML 元素,并对它们执行"操作"(actions).jQuery 语法jQuery 语法是通过选取 HTML 元素,并对选取 ...
- https 页面中引入 http 资源的解决方式
相对协议 应用场景 浏览器默认是不允许在 https 里面引用 http 资源的,一般都会弹出提示框. 用户确认后才会继续加载,用户体验非常差. 而且如果在一个 https 页面里动态的引入 http ...
- myeclipse 破解步骤
Fllow Orders.0. Close MyEclipse Application(if you wanna replace jar file).1. Fill usercode2. Fill s ...
- C#------获取最后一个"/"字符后面的所有内容
public ActionResult GetFile(string id) { var path = _db.MailAtchs.Where(p => p.MailID == new Guid ...
- PHP_$_SERVER_说明详解
PHP编程中经常需要用到一些服务器的一些资料,特把$_SERVER的详细参数整理下,方便以后使用. $_SERVER['PHP_SELF'] #当前正在执行 脚本的文件名,与 document roo ...
- C#实现录制屏幕
以前写过两篇录制麦克风语音和摄像头视频的文章(实现语音视频录制.在服务器端录制语音视频),最近有朋友问,如果要实现屏幕录制这样的功能,该怎么做了?实际上原理是差不多的,如果了解了我前面两篇文章中介绍的 ...
- 9-slice-scaling
9-slice-scaling http://rwillustrator.blogspot.com/2007/04/understanding-9-slice-scaling.html
- centos 7.0 ssh 登陆
CentOS 7.0 最小化安装 默认连接 默认端口是22 安装完查看IP 命令 ip addr ip: 192.168.1.103 自己家里练习的机子 都没改配置了 使用putty 远程连接 下载页 ...
- 浅谈T-SQL中的派生表和CTE
引言 表表达式是一种命名的查询表达式,代表一个有效的关系表.MSSQL支持4种类型的表表达式,它们分别是:派生表.公用表表达式(CTE).视图以及内联表值函数.表表达式并不是物理上真实存在的对象,它们 ...
- Java学习之Hessian通信基础
一.首先先说Hessian是什么? Hessian:hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能,相比WebService,Hessian更简 ...