题意:现在给以一棵$n$个结点的树,并给你$2k$个结点,现在要求你把这些节点互相配对,使得互相配对的节点之间的距离(路径上经过边的数目)之和最大。数据范围$1 \leq n \leq 200000, 2k \leq n$。

分析:贪心选择距离最大、次大...的结点对?貌似不对。暴力枚举所有可能?对但不可行。考虑节点对之间的距离实际上就是它们到LCA距离之和。因此单独考虑每个结点,它对答案的贡献实际上就是它到与其匹配节点的LCA的距离,这个距离必然不超过它到根的距离。如果我们有一种方法使得每个结点对答案的贡献都等于这个上界就好了,那么答案就是所有标记节点到根的距离之和。注意,要满足这个要求,与其匹配的结点应该和它不在根的同一个子树中,考虑根节点的各个子树中的标记节点,如果满足标记节点个数最多的子树不超过其余子树标记节点个数之和,那么是存在某种配对方法是得相互配对的节点分属不同子树的。即要求子树最大重量(含标记节点数目)不超过$k$即可(容易证明,讨论一下根是否是标记节点)。那么我们只需要对原图进行一次dfs找出这样的结点,并返回该节点作为根,再次dfs找出所有标记节点到根的距离之和即使答案。可以确定一定能够找到这样的根(提供一种证明思路,归纳法)。这样这道题可以在$O(n)$时间内解出。代码如下:

 #include <algorithm>
 #include <cstdio>
 #include <cstring>
 #include <string>
 #include <queue>
 #include <map>
 #include <set>
 #include <stack>
 #include <ctime>
 #include <cmath>
 #include <iostream>
 #include <assert.h>
 #pragma comment(linker, "/STACK:102400000,102400000")
 #define max(a, b) ((a) > (b) ? (a) : (b))
 #define min(a, b) ((a) < (b) ? (a) : (b))
 #define mp std :: make_pair
 #define st first
 #define nd second
 #define keyn (root->ch[1]->ch[0])
 #define lson (u << 1)
 #define rson (u << 1 | 1)
 #define pii std :: pair<int, int>
 #define pll pair<ll, ll>
 #define pb push_back
 #define type(x) __typeof(x.begin())
 #define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++)
 #define FOR(i, s, t) for(int i = (s); i <= (t); i++)
 #define ROF(i, t, s) for(int i = (t); i >= (s); i--)
 #define dbg(x) std::cout << x << std::endl
 #define dbg2(x, y) std::cout << x << " " << y << std::endl
 #define clr(x, i) memset(x, (i), sizeof(x))
 #define maximize(x, y) x = max((x), (y))
 #define minimize(x, y) x = min((x), (y))
 using namespace std;
 typedef long long ll;
 const int int_inf = 0x3f3f3f3f;
 const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
 ) - );
 const double double_inf = 1e30;
 ;
 typedef unsigned long long ul;
 typedef unsigned int ui;
 inline int readint(){
     int x;
     scanf("%d", &x);
     return x;
 }
 inline int readstr(char *s){
     scanf("%s", s);
     return strlen(s);
 }

 class cmpt{
 public:
     bool operator () (const int &x, const int &y) const{
         return x > y;
     }
 };

 int Rand(int x, int o){
     //if o set, return [1, x], else return [0, x - 1]
     ;
     int tem = (int)((double)rand() / RAND_MAX * x) % x;
      : tem;
 }
 ll ll_rand(ll x, int o){
     ;
     ll tem = (ll)((double)rand() / RAND_MAX * x) % x;
      : tem;
 }

 void data_gen(){
     srand(time());
     freopen("in.txt", "w", stdout);
     ;
     printf("%d\n", kases);
     while(kases--){
         ll sz = 1e18;
         printf());
     }
 }

 struct cmpx{
     bool operator () (int x, int y) { return x > y; }
 };
 ;
 int n, k;
 bool np[maxn];
 struct E{
     int to, nex;
 }e[maxn << ];
 int head[maxn], N;
 void addE(int x, int y){
     e[N].nex = head[x];
     e[N].to = y;
     head[x] = N++;
     e[N].nex = head[y];
     e[N].to = x;
     head[y] = N++;
 }
 int cnt[maxn];
 void dfs1(int u, int fa){
     cnt[u] = np[u];
     for(int i = head[u]; ~i; i = e[i].nex){
         int v = e[i].to;
         if(v == fa) continue;
         dfs1(v, u);
         cnt[u] += cnt[v];
     }
 }
 int rt;
 bool flag;
 void dfs2(int u, int fa){
     if(flag) return;
     ;
     ;
     for(int i = head[u]; ~i; i = e[i].nex){
         int v = e[i].to;
         if(v == fa) continue;
         maximize(maxi, cnt[v]);
         tot += cnt[v];
     }
     if(np[u]) ++tot;
     maximize(maxi,  * k - tot);
     if(maxi <= k){
         rt = u;
         flag = ;
         return;
     }
     for(int i = head[u]; ~i; i = e[i].nex) if(e[i].to != fa) dfs2(e[i].to, u);
 }
 ll dfs3(int u, int fa, int d){
     ll tem = ;
     if(np[u]) tem += d;
     for(int i = head[u]; ~i; i = e[i].nex){
         int v = e[i].to;
         if(v == fa) continue;
         tem += dfs3(v, u, d + );
     }
     return tem;
 }
 int main(){
     //data_gen(); return 0;
     //C(); return 0;
     ;
     if(debug) freopen("in.txt", "r", stdin);
     //freopen("out.txt", "w", stdout);
     while(~scanf("%d", &n)){
         k = readint();
         clr(np, );
         FOR(i, ,  * k) np[readint()] = ;
         N = , clr(head, -);
         FOR(i, , n){
             int x = readint(), y = readint();
             addE(x, y);
         }
         dfs1(, -);
         rt = ;
         flag = ;
         dfs2(, -);
         ll ans = dfs3(rt, -, );
         printf("%lld\n", ans);
     }
     ;
 }

code:

cf 700 B Connecting Universities的更多相关文章

  1. cf 701 E - Connecting Universities

    Descrition 给你一颗\(n\le 2*10^5\)个点的树, 有\(2*k(2k\le n)\)座大学座落在点上 (任二大学不在同一个点) 求一种两两匹配的方案, 使得距离和最大 即\[ma ...

  2. Codeforces Round #364 (Div. 2) E. Connecting Universities

    E. Connecting Universities time limit per test 3 seconds memory limit per test 256 megabytes input s ...

  3. Connecting Universities

    Connecting Universities Treeland is a country in which there are n towns connected by n - 1 two-way ...

  4. Codeforces Round #364 (Div. 2) E. Connecting Universities (DFS)

    E. Connecting Universities time limit per test 3 seconds memory limit per test 256 megabytes input s ...

  5. codeforces 701E E. Connecting Universities(树的重心)

    题目链接: E. Connecting Universities time limit per test 3 seconds memory limit per test 256 megabytes i ...

  6. Codeforces 701E Connecting Universities 贪心

    链接 Codeforces 701E Connecting Universities 题意 n个点的树,给你2*K个点,分成K对,使得两两之间的距离和最大 思路 贪心,思路挺巧妙的.首先dfs一遍记录 ...

  7. Codeforces 700B Connecting Universities(树形DP)

    [题目链接] http://codeforces.com/problemset/problem/700/B [题目大意] 给出 一棵n个节点的树, 现在在这棵树上选取2*k个点,两两配对,使得其配对的 ...

  8. Codeforces 700B Connecting Universities - 贪心

    Treeland is a country in which there are n towns connected by n - 1 two-way road such that it's poss ...

  9. cf701E Connecting Universities

    Treeland is a country in which there are n towns connected by n - 1 two-way road such that it's poss ...

随机推荐

  1. 我爱记单词(iWords)之NABC by张恿

    1) N (Need 需求) 我们组的项目是做一个英语学习助手,前人的基础上开发新的功能,修改原来功能的bug等等.之前的版本只提供了主动“看单词”和单词测试的功能,我们希望增加背单词的功能,以便更好 ...

  2. js 进度条,可实现结束和重新开始

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  3. Math-基本功能

    <script type="text/javascript"> /* *演示Math对象.该对象中的方法都是静态的.不需要new,直接Math调用即可 */ var n ...

  4. C语言输入多组问题~ungetc回退字符到stdin

    题目描述 输入数组长度 n 输入数组      a[1...n] 输入查找个数m 输入查找数字b[1...m]   输出 YES or NO  查找有则YES 否则NO . 输入描述: 输入有多组数据 ...

  5. Yii源码阅读笔记(二十三)

    Module类中的辅助功能方法: /** * Returns an ID that uniquely identifies this module among all modules within t ...

  6. [troubleshoot][archlinux][X] GPU HANG

    前言:如下内容已经是在hang完大概半个多月后了,当时想写,一直没过来写,写blog果然也是已经花费时间的事情. 最近一直在休假,电脑的使用频率也不多.后来还是为了生活,不情愿的去开始上班了,上班的第 ...

  7. 移除\禁用 jquery mobile 元素样式渲染

    在元素上加属性. data-role="none"

  8. How to prevent SQL injection attacks?

    In our earlier tutorial on SQL Injection, one way to have prevented the SQL injection attack was by ...

  9. elasticsearch使用操作部分

    本片文章记录了elasticsearch概念.特点.集群.插件.API使用方法. 1.elasticsearch的概念及特点.概念:elasticsearch是一个基于lucene的搜索服务器.luc ...

  10. cocos2dx 3.x(场景(层)的生命周期)

    //进入当前层初第一步始化层调用 bool GameScence::init() { if( !void init() ) { returnfalse; } log("进入当前层初第一步始化 ...