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)\)个点, 给出任意两点之间的最短路. 求最多可以去掉多少条边,使得任意两点的最短路长度不变. 思路 ...
随机推荐
- HDU #5733 tetrahedron
tetrahedron 传送门 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) P ...
- CF 321B Kefa and Company(贪心)
题目链接: 传送门 Kefa and Company time limit per test:2 second memory limit per test:256 megabytes Desc ...
- django admin中保存添加的数据提示need string or buffer, int found
原因 def __unicode__(self): return unicode(self.pk) 此处如果没有unicode就会报这个错误,原因就是编码错误 以为是文件开始没有加utf-8导致的,然 ...
- pycharm安装python模块
这个工具真的好好,真的很喜欢,它很方便,很漂亮,各种好 pycharm安装python模块:file-setting-搜索project inte OK
- JSP实现数据传递与保存
业务逻辑: 1.登陆login.jsp 2.判断登陆是否成功check.jsp 3.登陆成功页面newsDetail.jsp 4.登陆失败转发到login.jsp 代码如下: <%@ page ...
- JavaWeb---总结(十六)JSP指令
一.JSP指令简介 JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分. 在JSP 2.0规范中共定义了三个指令: pa ...
- Python实现打印二叉树某一层的所有节点
不多说,直接贴程序,如下所示 # -*- coding: utf-8 -*- # 定义二叉树节点类 class TreeNode(object): def __init__(self,data=0,l ...
- hdu 1873 看病要排队(优先级队列)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1873 题目大意: 三个医生看病,病人排队看病,病人有优先级,优先级高的提前看病,同样的优先级按先后.I ...
- ConterReplaceBehavior.class.php模板内容替换,如__PUBLIC__
ConterReplaceBehavior.class.php查找 __PUBLIC__ protected function templateContentReplace($content) { / ...
- AJAX笔试面试题汇总
AJAX笔试面试题汇总 Javascript 1. 什么是ajax,为什么要使用Ajax(请谈一下你对Ajax的认识) 什么是ajax: AJAX是“Asynchronous JavaScript a ...