[洛谷P3304] [SDOI2013]直径
洛谷题目链接:[SDOI2013]直径
题目描述
小Q最近学习了一些图论知识。根据课本,有如下定义。树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度。如果一棵树有N个节点,可以证明其有且仅有N-1 条边。
路径:一棵树上,任意两个节点之间最多有一条简单路径。我们用 dis(a,b)表示点a和点b的路径上各边长度之和。称dis(a,b)为a、b两个节点间的距离。
直径:一棵树上,最长的路径为树的直径。树的直径可能不是唯一的。
现在小Q想知道,对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。
输入输出格式
输入格式:
第一行包含一个整数N,表示节点数。 接下来N-1行,每行三个整数a, b, c ,表示点 a和点b之间有一条长度为c的无向边。
输出格式:
共两行。第一行一个整数,表示直径的长度。第二行一个整数,表示被所有直径经过的边的数量。
输入输出样例
输入样例#1:
6
3 1 1000
1 4 10
4 2 100
4 5 50
4 6 100
输出样例#1:
1110
2
说明
【样例说明】 直径共有两条,3 到2的路径和3到6的路径。这两条直径都经过边(3, 1)和边(1, 4)。
对于100%的测试数据:2<=N<=200000,所有点的编号都在1..N的范围内,边的权值<=10^9。
一句话题意: 给出一颗树,要求出树上所有直径相交的长度.
题解: 首先处理出树上的任意一条直径,然后处理出直径上的点到它的子树(不包含在直径上的点)中最深的距离.如果这个距离和它到直径一端的距离相同的话,就说明它的子树中含有直径中的一段.那么直径的这一段相同的长度都是不能算入最终全部直径相交的长度中的.
那么做法就可以得出了:确定一条直径,对直径上的每一个点判断它子树中是否存在有直径的一部分,如果有,那么就把指针向另一边移动,最后左右指针相减就是答案了.
最后答案要开long long
#include<bits/stdc++.h>
using namespace std;
const int N = 200000+5;
typedef int _int;
#define int long long
int n, last[N], ecnt = 0;
int pre[N], dep[N], fa[N], f[N], len = 0, L, R, vis[N], node[N], cnt = 0, mx[N], dist[N], ansl, ansr;
struct edge{
int to, nex, w;
}e[N*2];
void add(int x, int y, int z){
e[++ecnt].to = y, e[ecnt].w = z, e[ecnt].nex = last[x], last[x] = ecnt;
}
void dfs(int x, int las, int deep){
dep[x] = deep, fa[x] = las;
for(int to, i=last[x];i;i=e[i].nex){
to = e[i].to; if(to == las) continue;
dfs(to, x, deep+1);
if(len < f[x]+f[to]+e[i].w) len = f[x]+f[to]+e[i].w, L = pre[x], R = pre[to];
if(f[x] < f[to]+e[i].w) f[x] = f[to]+e[i].w, pre[x] = pre[to];
}
}
void get(int x, int lca){
if(x == lca){ node[++cnt] = x; return; }
get(fa[x], lca), node[++cnt] = x;
}
int get_dis(int x, int f){
int res = 0;
for(int to, i=last[x];i;i=e[i].nex){
to = e[i].to; if(to == f || vis[to]) continue;
res = max(res, e[i].w+get_dis(to, x));
}
return res;
}
void solve(){
int x = L, y = R, lca;
if(dep[x] < dep[y]) swap(x, y);
while(dep[x] > dep[y]) vis[x] = 1, x = fa[x];
if(x == y) vis[x] = 1, lca = x;
else {
while(x != y) vis[x] = vis[y] = 1, x = fa[x], y = fa[y];
vis[x] = 1, lca = x;
}
x = L, y = R;
while(x != lca) node[++cnt] = x, x = fa[x]; get(y, lca);
for(int i=1;i<=cnt;i++) mx[node[i]] = get_dis(node[i], -1);
for(int i=2;i<=cnt;i++)
for(int j=last[node[i]];j;j=e[j].nex)
if(e[j].to == node[i-1]) dist[node[i]] = dist[node[i-1]]+e[j].w;
ansl = 1, ansr = cnt;
for(int i=2;i <= cnt;i++)
if(dist[node[i]] == mx[node[i]]) ansl = i;
for(int i=cnt-1; i >= 1 && ansr >= ansl; i--)
if(dist[node[cnt]]-dist[node[i]] == mx[node[i]]) ansr = i;
}
_int main(){
ios::sync_with_stdio(false);
int x, y, z; cin >> n;
for(int i=1;i<=n;i++) pre[i] = i;
for(int i=1;i<n;i++) cin >> x >> y >> z, add(x, y, z), add(y, x, z);
dfs(1, -1, 1), solve();
cout << len << endl << ansr-ansl << endl;
return 0;
}
[洛谷P3304] [SDOI2013]直径的更多相关文章
- Bzoj3197/洛谷3296 [SDOI2013]刺客信条assassin(树的重心+树Hash+树形DP+KM)
题面 Bzoj 洛谷 题解 (除了代码均摘自喻队的博客,可是他退役了) 首先固定一棵树,枚举另一棵树,显然另一棵树只有与这棵树同构才有可能产生贡献 如果固定的树以重心为根,那么另一棵树最多就只有重心为 ...
- 【洛谷 P3304】[SDOI2013]直径(树的直径)
题目链接 题意,求一棵树被所有直径经过的边的条数. 这题是我们8.25KS图论的最后一题,当时我果断打了暴力求所有直径然后树上差分统计的方法,好像有点小问题,boom0了. 考完改这题,改了好久,各种 ...
- 洛谷 P3299 [SDOI2013]保护出题人 解题报告
P3299 [SDOI2013]保护出题人 题目描述 出题人铭铭认为给SDOI2012出题太可怕了,因为总要被骂,于是他又给SDOI2013出题了. 参加SDOI2012的小朋友们释放出大量的僵尸,企 ...
- 洛谷 P3297 [SDOI2013]逃考 解题报告
P3297 [SDOI2013]逃考 题意 给一个平面矩形,里面有一些有标号点,有一个是人物点,人物点会被最近的其他点控制,人物点要走出矩形,求人物点最少被几个点控制过. 保证一开始只被一个点控制,没 ...
- luogu P3304 [SDOI2013]直径
树的直径两遍dfs救星了 至于一定在直径中的边数,可以发现这些边一定是连续的(不然你两条直径中间能有空挡?),然后,如果某个点往下有多条直径,那么这条点以下都不算入答案.所以以直径分别两端点为根,找出 ...
- 洛谷 P3302 [SDOI2013]森林 解题报告
P3302 [SDOI2013]森林 题目描述 小\(Z\)有一片森林,含有\(N\)个节点,每个节点上都有一个非负整数作为权值.初始的时候,森林中有\(M\)条边. 小Z希望执行\(T\)个操作,操 ...
- 洛谷P3307 [SDOI2013]项链 [polya定理,莫比乌斯反演]
传送门 思路 很明显的一个思路:先搞出有多少种珠子,再求有多少种项链. 珠子 考虑这个式子: \[ S3=\sum_{i=1}^a \sum_{j=1}^a\sum_{k=1}^a [\gcd(i,j ...
- [bzoj3123][洛谷P3302] [SDOI2013]森林(树上主席树+启发式合并)
传送门 突然发现好像没有那么难……https://blog.csdn.net/stone41123/article/details/78167288 首先有两个操作,一个查询,一个连接 查询的话,直接 ...
- 洛谷 P3302 [SDOI2013]森林
->题目链接 题解: #include<queue> #include<cstdio> #include<cstring> #include<iostr ...
随机推荐
- DNS域名解析协议
一. 根域 就是所谓的“.”,其实我们的网址www.baidu.com在配置当中应该是www.baidu.com.(最后有一点),一般我们在浏览器里输入时会省略后面的点,而这也已经成为了习惯. 根域服 ...
- ajax与servlet交互(通过JSON),JAVA的arraylist传到前端的方法
所实现的效果:首先从前端(ajax)传参数给servlet,然后servlet经过处理,把arraylist类型的参数以JSON字符串的形式返回给前端(ajax),然后前端经过解析,把JSON字符串解 ...
- 利用JavaScriptSerializer类 进行Json对象的序列化和反序列化和过滤
项目下载:JavaScriptSerializer_对JSON对象序列化与反序列化及过滤器 利用<JavascriptSerializer类> 进行Json对象的序列化和反序列化 1. 首 ...
- DBGrid相关技术整理
DBGrid相关技术整理: 注:对于DBGrid相关属性.方法的学习融入到技术整理过程中 一,多选 设置属性: Options->dgMultiSelect = True; ->dgRow ...
- asp.net获取文件绝对路径
一般我们在asp.net中使用HttpContext.Current.Request.MapPath或者 HttpContext.Current.Server.MapPath来获取文件的绝对路径, p ...
- 【其他】VS提示不一致的行尾
应该是用不同的编辑器或平台编辑过同一个文件,比如Windows是\r\n,有的系统只有一个\n, 需要都统一,否则代码可能会堆成一堆.
- Activiti5工作流笔记二
流程变量 import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.activiti ...
- bzoj1835[ZJOI2010]基站选址
主席树+决策单调,重写一遍比之前短多了……题解:http://www.cnblogs.com/liu-runda/p/6051422.html #include<cstdio> #incl ...
- HTML5 不再支持哪些元素
HTML5中已经不支持以下的元素,不建议在进行开发时再使用以下的元素. 1.acronym(建议abbr):定义首字母缩写 2.applet(建议object):定义applet 3.basefont ...
- P1667 数列
题目描述 给定一个长度是n的数列A,我们称一个数列是完美的,当且仅当对于其任意连续子序列的和都是正的.现在你有一个操作可以改变数列,选择一个区间[X,Y]满足Ax +Ax+1 +…+ AY<0, ...