Codeforces Round #665 (Div. 2) D. Maximum Distributed Tree(DFS+贪心)

题目链接:https://codeforces.ml/contest/1401/problem/D

题意:n个点,n-1条边,一个数k拆分成若干个素因数将其放置在边上,f(i,j)表示从i顶点到j顶点的边权和,求

的最大值。

题解:很明显的贪心题,边经过的次数越多,放置的数字越大,因此要先求出每条边经过的次数再从大到小排序,最后分n和m的关系讨论,重点在于如何求每条边的次数,开一个数组sz表示子树大小(节点数),经过边的次数=(n-sz[i])*sz[i],这边简单证明一下,我们从树种任意选取一条边,这条边将树划成2部分,设该边的上半部分节点数为a,则另一边节点数为n-a,对于上半部分的任意一个节点经过该边次数都为n-a,上半部分共有a个点,因此是a*(n-a)。还有一个小坑,在算边的次数时不能先取余再排序,否则会WA在第5个测试点。

代码:

#include
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
const int mod=1e9+7;
vector e[maxn];
ll a[maxn],sz[maxn];
int n,m;
void dfs(int x,int fa){	//算子树大小 
	for(int i=0;i>T;
	while(T--){
		cin>>n;
		for(int i=1;i<=n;i++) e[i].clear();
		for(int i=0;i>x>>y;
			sz[x]=1;sz[y]=1;
			e[x].push_back(y);
			e[y].push_back(x);
		}
		cin>>m;
		for(int i=1;i<=m;i++) cin>>a[i];
		sort(a+1,a+m+1,greater());
		dfs(1,-1);
		vector v;
		for(int i=1;i<=n;i++) v.push_back((n-sz[i])*sz[i]); //不能取模 
		sort(v.begin(),v.end(),greater()); 
		ll ans=0;
		if(n-1>=m){		
			for(int i=0;i

 

你可能感兴趣的:(codeforces,数据结构)