首页 > 其他分享 >CF1294F 题解

CF1294F 题解

时间:2024-08-13 16:52:39浏览次数:13  
标签:int 题解 边权 dfs stk 直径 CF1294F dis

Part.0 闲话

更好的观看体验

目前题解区里大多数巨佬都是采用的树形 dp 和暴力等方法,看见没有我这种做法,欢迎指出做法问题或 hack 代码。

Part.1 题意

给定一棵树,选 \(3\) 个点 \(a, b, c\),求 \(a\) 到 \(b\) 的路径与 \(a\) 到 \(c\) 的路径与 \(b\) 到 \(c\) 的路径上一共有多少不重复的边。

Part.2 分析

我们不妨把每条边的边权设为 \(1\),这样方便我们计算贡献。

仔细思考一下后,可以发现无论如何,先把树的直径的端点选上最优,而 \(c\) 也一定是在某一个距离直径上点最远的点。

但是一个问题诞生了,怎么求这个距离最远的点呢?枚举直径上点再搜的时间复杂度是 \(O(n^2)\) 的,肯定会超时。

这时候,前文将边权设为 \(1\) 的好处就凸显出来了。

我们可以把所有直径上的边的边权全部设置为 \(0\),然后从直径的某一个端点再次搜索一遍树的直径,那么新直径的另一个端点就是我们要求的 \(c\),起点可以选在直径上的任意一点,因为此时在直径上搜不会增加答案的值。

所以答案就是旧直径的长加新直径的长。

Part.3 代码

#include <bits/stdc++.h>

using namespace std;

const int kMaxN = 2e5 + 5;

struct Node {
	int v, w, nxt;
} e[kMaxN << 1];

int n;
int dis, x;
int res, a, b, c;
int hd[kMaxN], cnt = 1;
vector<pair<int, int>> stk, d;

void add(int u, int v) {
	e[++cnt].nxt = hd[u];
	hd[u] = cnt;
	e[cnt].v = v;
	e[cnt].w = 1;
}

void dfs(int u, int fa, int s) {
	if (s >= dis) {
		dis = s;
		if (u != a && u != b && u != c) {
			x = u;
			d = stk;
		}
	}
	for (int i = hd[u]; i; i = e[i].nxt) {
		int v = e[i].v, w = e[i].w;
		if (v == fa) {
			continue;
		}
		stk.push_back({u, i});
		dfs(v, u, s + w);
		stk.pop_back();
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1, a, b; i < n; i++) {
		cin >> a >> b;
		add(a, b);
		add(b, a);
	}
	dis = 0;
	dfs(1, 0, 0);
	a = x;
	dis = 0;
	dfs(x, 0, 0);
	b = x;
	res += dis;
	dis = 0;
	for (auto i : d) {
		e[i.second].w = e[i.second ^ 1].w = 0;
	}
	dfs(x, 0, 0);
	c = x;
	res += dis;
	cout << res << '\n' << a << ' ' << b << ' ' << c << '\n';
	return 0;
}

值得注意的是,一定要使用链式前向星并且把双向的边全部边权赋为 \(0\)。因为我太菜了,所以只能开个栈储存直径上的边,事实上可以边搜边赋值。

时间复杂度 \(O(n)\),常数可能有一点大。

标签:int,题解,边权,dfs,stk,直径,CF1294F,dis
From: https://www.cnblogs.com/Yun-Mengxi/p/18357275

相关文章

  • 新坑:信息学奥赛一本通题解(3001~3005)
    前言Hello,大家好我是文宇,开个新坑,是关于信息学奥赛一本通的坑,就是信奥赛题解.(这里指编程启蒙的题库)因为作者的洛谷还在写,只是信奥赛的题写的比较多,所以先做信奥赛的.信奥赛的网址是信息学奥赛一本通-编程启蒙(C++版)在线评测系统(挖坑:作者以后可能还会有信奥赛本体......
  • 生活在hzoi上 题解
    生活在hzoi上题解考虑有两棵树怎么做,显然是\(y^{n-k}=y^{n-\left\vertE_1\capE_2\right\vert}\)其中\(E_1\)和\(E_2\)是两棵树的边集发现上边那个\(k\)是两棵树边集交构成的图的连通块个数\(\left\vertE_1\capE_2\right\vert\)就是两棵树交的连通块数量......
  • 记一次NoClassDeffoundEror问题解决过程
    背景:在对某台计算服务器进行代码修改后,发现es查询报错,抛出异常如下: 思路: 1.jar包冲突   查询了对应jar的pom文件,发现只有一个es的版本jar包,不存在冲突,百思不得其解。2.本地环境问题   清理idea的缓存,发行问题仍然存在最后翻阅资料,打了断点追踪异常抛出的地方,......
  • ARC182 题解
    A-ChmaxRush!发现一个数能向哪边覆盖只由再他之后操作且\(v\)比他大的操作决定。所以扫一遍确定方向之后乘起来就好。B-|{floor(A_i/2^k)}|首先不难发现\(<2_{k-1}\)的元素是无用的,因为它们会由\(\ge2^{k-1}\)的元素除以2的幂得到。先想上界。对于\(0\l......
  • ARC182B |{floor(A_i/2^k)}| 题解
    ARC182B|{floor(A_i/2^k)}|题解题目大意定义一个长度为\(N\)的序列\(A\)的分数为能被表示成\(\lfloor{A_i\over2^k}\rfloor\)的数的个数,其中\(i=1,2,\dots,N\),\(k\)为任意自然数。给定\(N,K\),求长度为\(N\)且元素大小都在\(2^K-1\)内的所有序列的分数的最大值......
  • 【题解】 [USACO 2007 FEB] Cow Party S
    题目描述题目大意给定一个有向图,以及一个顶点。求其他所有点到给定点,再从给定点回到各自起始点的最短路中的最大值。思路本题主要考查:对单源最短路算法的熟练运用。最短路总共分为2段:其他所有点到给定点、给定点回到各自起始点。首先求第一段:可以在原图的基础上建一个反向图......
  • 洛谷 P4305 不重复数字——题解
    洛谷P4305题解传送锚点摸鱼环节[JLOI2011]不重复数字题目描述给定\(n\)个数,要求把其中重复的去掉,只保留第一次出现的数。输入格式本题有多组数据。第一行一个整数\(T\),表示数据组数。对于每组数据:第一行一个整数\(n\)。第二行\(n\)个数,表示给定的数。输出格......
  • 【题解】 热浪
    题目描述【题目描述】德克萨斯纯朴的民眾们这个夏天正在遭受巨大的热浪!!!他们的德克萨斯长角牛吃起来不错,可是他们并不是很擅长生產富含奶油的乳製品。FarmerJohn此时以先天下之忧而忧,后天下之乐而乐的精神,身先士卒地承担起向德克萨斯运送大量的营养冰凉的牛......
  • [题解 hduoj-7522] 2024HDU 暑假多校7 - cats 的最小生成树
    原题链接题意有一个有重边的无向图,每次找到它的最小生成树,并删除生成树的边,直到不存在最小生成树,问被每条边在第几次被删除.思路考虑用类似Kruskal算法,但是是遍历一遍所有边,同时处理出来所有的生成树.具体这样做:如Kruskal一样,把所有边按边权排序,......
  • GBNC 题解
    GBNC题解这可比平时做的红题难吧。题目以思维为主,和CCF的趋势有点挂钩。题目实际难度:橙-,橙,橙,黄。不知道从哪听到的消息,说你们的信息思维都特别好,所以就没有大红题了。T1思路这道题我们能用模拟来写。我们可以将这整个询问分为\(n\)个小询问。每次询问我们用一个整形\(......