首页 > 其他分享 >Codeforces 87D Beautiful Road

Codeforces 87D Beautiful Road

时间:2023-03-18 14:55:56浏览次数:53  
标签:Beautiful 魅力值 fa int 加入 Codeforces dep 权值 87D

Codeforces 87D Beautiful Road

CF传送门

Description

​ 给定一个无向图,\(n\) 个点,\(n-1\) 条边,保证图联通(就是一棵树),并且给定每条边的权值。任取两个点,连接二者的路径上权值最大的边(可以不止一条)的魅力值+2。求边的最大魅力值,以及该魅力值对应的所有边。

Solution

参考题解1 参考题解2

​ 先考虑两种特殊情况:

​ (1)若所有的边权值都相等:对于每条边,假设它的两边连接的点数分别为 \(x,y\) ,则该边的魅力值为 \(x*y*2\)。只需要建立一棵树,遍历一遍统计已任意结点为根的子树结点数,便可计算所有边的魅力值,从而得出答案。(若以\(rt1\)为根的子树大小为\(m\),则连接\(rt1\)和它的父结点的边的魅力值为 \(m*(n-m)\) )

​ (2)若所有边权值都不等:考虑按照权值从小到大地向图中加入边,用并查集维护联通性,当加入第 \(i\) 条边时,将加入它之前两个顶点所在地并查集大小相乘(再乘上\(2\))便可得到该边魅力值。将所有边加入后,也就得到了答案。

​ 在本题中,对边的权值没有限制,也就是说既有不同的也有相同的。所以,如果直接应用上述\((2)\)中的方法是不对的。可以想到,应该按照权值从小到大,但是一次不是只加入一条边,而是应该加入权值相等的所有边,然后统计这些边的答案,再进行下一轮加边。

​ 那么现在的问题就是,在一次性加入相等权值的边之后如何统计这些边的魅力值。在上述\((2)\)中,统计边的答案是在加边之前,但是现在必须是在加边之后。考虑能否确定一种在权值相等时边的加入顺序,使得在加入这些边之后,边的某个端点连接点数不会改变。

​ 以任意点为根建一棵树,将相等的边按照由深到浅的顺序加入,这样一来,边连接的更深的点所连的结点数(或者说,并查集大小,或者说,当前子树大小)是不会改变的,在加入边之前记录这个值,等所有同等权值的边加入后,就可以利用前面临时记录的值和边所在的并查集总大小统计答案了。(感觉说得有点抽象,可以自己想象一下 \(qwq\))

Code

//by DTTTTTTT 2023.3.14
#include<iostream>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 1e5 + 5; //当然不能只写1e5啦
int n, fa[N], Size[N], dep[N], tmp[N];
vector<int>to[N];
ll val[N];
struct edge {
	int u, v, id, dep;
	ll w;
}e[N];
bool cmp(edge x,edge y){
	if (x.w == y.w)
		return x.dep > y.dep;
	return x.w < y.w;
}
int find(int x) {
	return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void join(int i, int u, int v) {
	int fu = find(u), fv = find(v);
	tmp[i] = Size[fv];
	fa[fu] = fv;
	Size[fv] += Size[fu];
}
void dfs(int u, int fa, int depp) {
	dep[u] = depp;
	for (int i = 0;i < to[u].size();++i) {
		int v = to[u][i];
		if (v == fa) continue;
		dfs(v, u, depp + 1);
	}
}
int main() {
	cin >> n;
	for (int i = 1;i < n;++i) {
		cin >> e[i].u >> e[i].v >> e[i].w;
		e[i].id = i;
		to[e[i].u].push_back(e[i].v);
		to[e[i].v].push_back(e[i].u); //这一步写错结果debug半天,,
	}

	for (int i = 1;i <= n;++i)
		fa[i] = i, Size[i] = 1;

	dfs(1, 0, 0);
	
	for (int i = 1;i < n;++i) {
		if (dep[e[i].u] > dep[e[i].v])
			swap(e[i].u, e[i].v);  //e[i].v是更深的点
		e[i].dep = dep[e[i].v];
	}

	sort(e + 1, e + n, cmp);

	int num = 0;
	for (int i = 1;i < n;++i) {
		int u = e[i].u, v = e[i].v, w = e[i].w;
		join(i, u, v), ++num;
		if (i == n - 1 || w != e[i + 1].w) {
			for (int j = i - num + 1;j <= i;++j)
				val[e[j].id] = 1ll * tmp[j] * (Size[find(e[j].u)] - tmp[j]) * 2;
			num = 0;
		}
	}

	num = 0;
	ll maxval = 0;  //写ll!!!
	for (int i = 1;i < n;++i)
		if (maxval < val[i])
			maxval = val[i], num = 1;
		else if (maxval == val[i])
			++num;

	cout << maxval << " " << num << endl;
	for (int i = 1;i < n;++i)
		if (maxval == val[i])
			cout << i << " ";
	
	return 0;
}

标签:Beautiful,魅力值,fa,int,加入,Codeforces,dep,权值,87D
From: https://www.cnblogs.com/dttttttt/p/17230619.html

相关文章

  • beautifulsoup
    Beautifulsouphtml标签转化成树结构结构化输出tag树soup=BeautifulSoup(html_doc,'html.parser')print(soup.prettify())按照点的方式寻找标签soup.title #title......
  • BeautifulSoup模块的使用方法
    本篇文章主要讲bs4模块(BeautifulSoup),这个模块能做么呢?用一句话来概括的话:beautifulsoup4从HTML或XML文件中提取数据的Python库,用它来解析爬取回来的xml。从而从网站中......
  • Codeforces Round 350 (Div. 2) ABCD1D2
    https://codeforces.com/contest/670A.Holidays题目大意:给定n天,求出可以休息的最大小时间和最大时间。input14output44#include<bits/stdc++.h>usingnamesp......
  • Codeforces Round 851 (Div. 2) (CF1788) 题解
    CF1788AOneandTwo对于一个序列,题目要求蓝色部分的乘积等于绿色部分的乘积,因为序列中只有\(1\)和\(2\),所以我们只要蓝色部分和绿色部分的\(2\)的数量相等即可,使用......
  • Codeforces Round 406 (Div. 1) C. Till I Collapse 主席树上二分
    首先贪心是显然的,但是询问有n个先考虑一个朴素的主席树做法对于每个k,对于当前固定的L,二分R,用主席树查询一下[L,R]区间内的不同数个数是否大于K个(主席树的经典应用),更新......
  • Educational Codeforces Round 2 E Lomsat gelral 线段树合并
    题目链接大致题意给你一棵有n个点的树,树上每个节点都有一种颜色ci(ci≤n),让你求每个点子树出现最多的颜色/编号的和记性不好,主要是为了防止自己忘掉,今天和队友合作写题......
  • Codeforces Round 855 (Div. 3)
    之前立下了一个flag,每个有空的下午做一套CF来增长智商。题目地址G.Symmetree问题的本质如何快速比对两个子树是否相同。考虑树hash。这里采用的是主流的AHU算法(安徽......
  • Codeforces Round 857 (Div. 2) A. Likes
    linkCode//#include<bits/stdc++.h>#include<iostream>#include<cstring>#include<algorithm>#include<vector>#include<queue>#include<cmath>#include......
  • The Very Beautiful Blanket (贪心给问题增加限制条件,构造,位运算)
        法一:贪心得缩小调价:让每一个矩阵的值都是一样的性质:  捞捞利用位运算的性质,每次+4,因为4是二ni次,就是一直在某个位上面加一个东西然后在第......
  • Educational Codeforces Round 105 (Rated for Div
    EducationalCodeforcesRound105(RatedforDiv.2)ABCString给定一个字符串只有A、B和C构成。要求替换A、B、C为')'和'(',并且相同字母替换的是一样的,使得字符串变......