题意:给你一棵树,要求对k个结点涂色,然后统计每个未涂色结点到根结点的路径上未涂色结点的和,求和最大能为多少
题解:对着样例画几遍,然后贪心发现,最优解一定是当前结点的深度减去它的子结点个数大的来涂色,然后直接就建树进行dfs就行了,其实这道题可以作为一道模板题qwq(比赛没写出来主要还是不会建树(⊙﹏⊙)b)
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <stack> 7 #include <queue> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <unordered_set> 12 #include <unordered_map> 13 #define ll long long 14 #define fi first 15 #define se second 16 #define pb push_back 17 #define me memset 18 const int N = 1e6 + 10; 19 const int mod = 1e9 + 7; 20 using namespace std; 21 typedef pair<int,int> PII; 22 typedef pair<long,long> PLL; 23 24 int n,k; 25 int u,v; 26 ll sum; 27 int pos[N],cnt[N]; 28 vector<int> s[N]; 29 vector<int> res; 30 31 void dfs(int u,int pre){ 32 pos[u]=pos[pre]+1; 33 cnt[u]=1; 34 vector<int>::iterator iter; 35 for(iter=s[u].begin();iter!=s[u].end();++iter){ 36 if(*iter==pre) continue; 37 dfs(*iter,u); 38 cnt[u]+=cnt[*iter]; 39 } 40 res.pb(pos[u]-cnt[u]); 41 } 42 43 int main() { 44 ios::sync_with_stdio(false); 45 cin>>n>>k; 46 for(int i=1;i<n;++i){ 47 cin>>u>>v; 48 s[u].pb(v); 49 s[v].pb(u); 50 } 51 dfs(1,0); 52 sort(res.begin(),res.end()); 53 reverse(res.begin(),res.end()); 54 for(int i=0;i<k;++i) sum+=(ll)res[i]; 55 printf("%lld\n",sum); 56 57 58 return 0; 59 }