2017百度之星初赛B-1002(HDU-6115)
一、思路
这题“看似”比较难搞的一点是,一个节点上有多个办公室,这怎么求?其他的,求树中任意两个节点的距离(注意:没有最远或最最进这一说法,因为树上任意两个节点之间有且仅有一条路径。不然就有回路了,对吧。)都不是特别难的问题。
(1)如何找到任意两个公司之间的最短距离?没有很好的办法,只能暴力。记录每个公司的每个办公室所在节点,求指定两个公司A和B的最短距离时,枚举公司A的所有办公室所在节点,再枚举公司B的所有办公室所在节点,求出被枚举的节点之间的距离,然后,取最小的那一个输出。
(2)求树中任意两个节点的距离?我一开始用的是Tarjan求LCA的算法,然后,交上去TLE了两发。后来换了一种策略,记录每个节点的深度、它的父节点以及它到父节点之间的距离。求任意两个点的LCA的时候,采用谁深度大谁先上移的方法,然后移动过程中记录移动了多少距离,当两个点移动到一个点时,这个点就是他们的LCA,返回记录的距离即可。这样,可以避免求子节点到根节点的距离(即麻烦又要多写很多不必要的代码)。另外一点,要不要先求出树的重心来优化时间复杂度,我用第二种策略提交的第一份AC的代码,求了树重心,耗时:8595MS;后来直接把求重心的代码去掉,直接把1号节点当总根节点,耗时:8782MS,差不多。所以,我下面贴的代码就没求树的重心了,这样代码也简洁了好多,关键函数就只有一个:找到给定两个节点的LCA并返回它们之间的距离。
二、代码
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int INF = 0x3fff3fff;
const int MAXN = 100010;
typedef struct {
int to, wt, next;
} Edge;
Edge tree[MAXN * 2];
int head[MAXN], cnt;
int n, m, q;
/**office[i][j]:公司i的第j个办公室所在节点。*/
vector<int> office[MAXN];
void add(int from, int to, int wt) {
tree[cnt].to = to;
tree[cnt].wt = wt;
tree[cnt].next = head[from];
head[from] = cnt++;
}
void init() {
memset(head, -1, sizeof(head));
cnt = 0;
for(int i = 0; i < MAXN; ++i)office[i].clear();
}
/** deep[i]:i节点的深度。
f[i]:i节点的父节点。
len2f[i]:i节点到父节点的长度。
*/
int deep[MAXN], f[MAXN], len2f[MAXN];
/**
d:深度。总根(树的重心)节点的深度为0。
*/
void dfsDep(int root, int par, int d) {
deep[root] = d;
f[root] = par;
for(int i = head[root], to = -1; i != -1; i = tree[i].next) {
to = tree[i].to;
if(to != par) {
len2f[to] = tree[i].wt;
dfsDep(to, root, d + 1);
}
}
}
int getDis(int a, int b) {
int res = 0;
while(deep[a] < deep[b]) {
res += len2f[b];
b = f[b];
}
while(deep[a] > deep[b]) {
res += len2f[a];
a = f[a];
}
while(a != b) {
res += len2f[a] + len2f[b];
a = f[a];
b = f[b];
}
return res;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif // ONLINE_JUDGE
int t, a, b, c;
scanf("%d", &t);
while(t--) {
init();
scanf("%d%d", &n, &m);
for(int i = 1; i < n; ++i) {
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
for(int i = 1; i <= m; ++i) {
scanf("%d", &a);
for(int k = 0; k < a; ++k) {
scanf("%d", &b);
office[i].push_back(b);
}
}
dfsDep(1, -1, 0);
scanf("%d", &q);
for(int i = 1; i <= q; ++i) {
scanf("%d%d", &a, &b);
c = INF;
for(int j = 0, asz = office[a].size(); j < asz; ++j) {
for(int k = 0, bsz = office[b].size(); k < bsz; ++k) {
c = min(c, getDis(office[a][j], office[b][k]));
if(c == 0) {j = asz; break;}
}
}
printf("%d\n", c);
}
}
return 0;
}
2017百度之星初赛B-1002(HDU-6115)的更多相关文章
- 2014百度之星初赛第二场hdu 4831 Scenic Popularity
Scenic Popularity Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- 2019 年百度之星 初赛一 1002 Game
传送门 Problem Description 度度熊在玩一个好玩的游戏.游戏的主人公站在一根数轴上,他可以在数轴上任意移动,对于每次移动,他可以选择往左或往右走一格或两格.现在他要依次完成 n 个任 ...
- HDU - 6112 2017百度之星初赛A 今夕何夕
今夕何夕 Accepts: 1345 Submissions: 5533 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/ ...
- HDU 6118 2017百度之星初赛B 度度熊的交易计划(费用流)
度度熊的交易计划 Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- HDU 6119 2017百度之星初赛B 小小粉丝度度熊 (二分)
小小粉丝度度熊 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- HDU - 6114 2017百度之星初赛B Chess
Chess Accepts: 1805 Submissions: 5738 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768 ...
- HDU - 6113 2017百度之星初赛A 度度熊的01世界
度度熊的01世界 Accepts: 967 Submissions: 3064 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 327 ...
- 2017百度之星初赛A-1006(HDU-6113)
思路:在图的外面包一圈'0'字符,然后dfs统计'0'字符的个数和'1'字符的个数.结果如下(num0表示0字符的个数,num1表示1字符的个数): num0 == 1 && num1 ...
- 2017"百度之星"程序设计大赛 - 初赛(A) [ hdu 6108 小C的倍数问题 ] [ hdu 6109 数据分割 ] [ hdu 6110 路径交 ] [ hdu 6112 今夕何夕 ] [ hdu 6113 度度熊的01世界 ]
这套题体验极差. PROBLEM 1001 - 小C的倍数问题 题 OvO http://acm.hdu.edu.cn/showproblem.php?pid=6108 (2017"百度之星 ...
随机推荐
- PentesterLab-PHP Include And Post Exploitation
一.打开页面,看到这么个页面,按照惯例随手点一点 二.Login处显然是一个后台登录页面,但前提是的有账号密码,看了下Submit这个页面,发现url中有个page参数 三.nikto跑一下这个页面. ...
- 一个好工具-everything-可以找到浏览器的所有缓存
下载路径http://www.voidtools.com/downloads/ 我用它来寻找浏览器缓存的google瓦片.
- flowable FormEngine和FormEngineConfiguration
FormEngineConfiguration 继承自 AbstractEngineConfiguration. 一.获得实例 FormEngineConfiguration提供了7个公开的静态方法: ...
- 有关项目依赖包发生 Manifest Merge 冲突的详细解决方案
安卓开发使用 Gradle 插件管理依赖包确实非常方便,尤其是在解决一些依赖冲突的问题上.比如,重复依赖的问题,具体内容请我之前写的一篇文章: 有关 Android Studio 重复引入包的问题和解 ...
- Swift UIAlertController、UISegmentedControl
// MARK: 提示框 func _initAlertView() { let btn = UIButton(type: UIButtonType.ContactAdd) btn.frame = C ...
- baos bais 意义
import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOut ...
- 【转载】VMware vSphere 5 HA详解 1
很久没有动笔写博客了.总算最近的几项工作告一段落,对iOS和Android的折腾也兴趣稍退,该写点技术博客了. 想写一篇关于VMware HA的博客由来已久,曾经做了些功课,查了不少资料,写了点笔记, ...
- BZOJ - 3223 Tyvj 1729 文艺平衡树 (splay/无旋treap)
题目链接 splay: #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3f3f3f ...
- HDU1556 线扫
昨天睡得太晚,今天又在看新算法,明天事情也多,烦,所以今天刷刷水题就过去了. 叫我用线段树,我反而搞不来 #include<cstdio> #include<cstdlib> ...
- Codeforces 620E New Year Tree【线段树傻逼题】
LINK 题目大意 给你一棵树 让你支持子树染色,子树查询颜色个数,颜色数<=60, 节点数<=4e5 思路 因为颜色数很少,考虑状态压缩变成二进制 然后直接在dfs序上用线段树维护就可以 ...