Linova and Kingdom(dfs)(题解)

**

2020/7/10补题Linova and Kingdom(DFS)

**

Writing light novels is the most important thing in Linova’s life. Last night, Linova dreamed about a fantastic kingdom. She began to write a light novel for the kingdom as soon as she woke up, and of course, she is the queen of it.

There are n cities and n−1 two-way roads connecting pairs of cities in the kingdom. From any city, you can reach any other city by walking through some roads. The cities are numbered from 1 to n, and the city 1 is the capital of the kingdom. So, the kingdom has a tree structure.

As the queen, Linova plans to choose exactly k cities developing industry, while the other cities will develop tourism. The capital also can be either industrial or tourism city.

A meeting is held in the capital once a year. To attend the meeting, each industry city sends an envoy. All envoys will follow the shortest path from the departure city to the capital (which is unique).

Traveling in tourism cities is pleasant. For each envoy, his happiness is equal to the number of tourism cities on his path.

In order to be a queen loved by people, Linova wants to choose k cities which can maximize the sum of happinesses of all envoys. Can you calculate the maximum sum for her?

Input
The first line contains two integers n and k (2≤n≤2⋅105, 1≤k<n) — the number of cities and industry cities respectively.

Each of the next n−1 lines contains two integers u and v (1≤u,v≤n), denoting there is a road connecting city u and city v.

It is guaranteed that from any city, you can reach any other city by the roads.

Output
Print the only line containing a single integer — the maximum possible sum of happinesses of all envoys.

Input
7 4
1 2
1 3
1 4
3 5
3 6
4 7
Output
7
Input
4 1
1 2
1 3
2 4
Output
2
Input
8 5
7 5
1 7
6 1
3 7
8 3
2 1
4 5
Output
9
题意:
给你一颗树共有n个节点,且无向,让你在这棵树上找到k个工业节点,其余都为旅游节点,计算出每个工业节点走到1号节点经过的旅游节点数目sum,问你怎样选择这k个工业节点,使sum最大。

思路:
建立好树,令1号节点的深度是1,然后往下走,当遍历到的点是叶子节点时,该点的贡献是该点到1号节点的距离(deep-1),当该点不是叶子节点时该点的贡献是deep-cnt(cnt为算上自己和自己所有子子孙孙且都认为是工业节点的数量)。这样得到的数组进行降序排序,并将前k个累加得到的便是答案。

Note:
为什么当一个节点不是叶子节点的时候他的贡献是deep-cnt呢?按道理来说不应该也是它到1号节点的距离吗?因为当它不是叶子节点时,它的子节点也已经是工业节点了,当自己是工业节点时就会对自己的子节点的权值造成影响,但这时递归不回去了,所以就将子节点的影响加在了自己的身上。在最后求sum的时候就不会造成影响。

#include<list>
#include<string.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<deque>
#include<stack>
#include<queue>
#include<set>
#include<iomanip>
#include<cstdlib>
#include<stdexcept>
#include<fstream>
#include<iterator>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
const int inf = 0x3f3f3f3f;
const double PI = acos(-1);
const double eps = 1e-7;
const int mod = 998244353;
#define speed {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); }

inline int gcd(int a, int b)
{
	while (b ^= a ^= b ^= a %= b);
	return a;
}
vector<int>Edge[maxn];//用来存边的信息
vector<int>res;//用来存一个节点的值
int dfs(int now,int pre,int deep)//用来得出当前节点后面有几个工业节点(包含自己本身)
{
	int cnt=1;//将自己视为工业节点
	for(int i=0;i<Edge[now].size();i++)
	{
		if(Edge[now][i]==pre)continue;
		int nownext=Edge[now][i];
		cnt+=dfs(nownext,now,deep+1);
	}
	res.push_back(deep-cnt);//计算权值
	return cnt;
}
int main()
{
    int n,k;
	scanf("%d %d",&n,&k);
	n--;
	while(n--)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		Edge[a].push_back(b);
		Edge[b].push_back(a);
	}
	dfs(1,0,1);//令开始的深度为1
	sort(res.begin(),res.end());
	//for(int i=0;i<res.size();i++)printf("%d%c",res[i]," \n"[i==res.size()-1]);
	reverse(res.begin(),res.end());//将数组翻转变为降序排序
	ll sum=0;//如果是int就会爆,应该会出现wa on tset 9;
	for(int i=0;i<k;i++)sum+=res[i];
	printf("%lld\n",sum);
	//system("pause");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值