题意:现在给以一棵$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. ZK 代码自动提示

    1.设置xsd 打开eclipse,Window-Preference,进行如下设置: 2.创建zul文件 (1)打开File—New—Other窗口,新建XML File文件: (2)选择新建文件所 ...

  2. 2016HUAS暑假集训训练2 E - I Hate It

    Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老 ...

  3. 想通过加HINT让其走全表扫描

    一个SQL,通过SPM固定它的执行计划,可以通过DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE实现.也可以通地此功能在不修改原SQL的情况下对其加HINT来固定执行计划.D ...

  4. IOS第16天(4,Quartz2D柱状图)

    *** #import "HMBarView.h" #import "UIColor+Random.h" @implementation HMBarView - ...

  5. python随机服务器的双线出口ip发送邮件

    #-*- coding:utf-8 -*-import smtplibimport sysimport random import socketfrom email.mime.text import ...

  6. 初探XML

    1.XML是什么? XML 指可扩展标记语言(EXtensible Markup Language) XML 是一种标记语言,很类似 HTML XML 的设计宗旨是传输数据,而非显示数据 XML 标签 ...

  7. 一个相比jdk的io包更方便处理数据读写的包

    apche的commons-io.jar包,里面有个类IOUtils,提供的下列方法: readLines方法能够从字节输入流或字符输入流里读取数据,按行读,返回字符串组成的list write方法能 ...

  8. Java工具

    1. Groovy shell 可以在Java代码里执行脚本,可以将Java方法配置在文件里 依赖 <dependency> <groupId>org.codehaus.gro ...

  9. SEO之HTML优化:让你的网站HTML代码更符合SEO规范

    摘要HTML优化是网站内部优化的重点,可能对SEO新手来说,容易忽略.符合搜索引擎习惯的HTML代码是极利于SEO的,可以让你的网站获得更好的搜索引擎排名.如何制作一个标准的HTML网页,如何做HTM ...

  10. App_global.asax.pdb: 另一个程序正在使用此文件,进程无法访问。

    页面修改后,浏览报错,信息如下. 编译错误 说明: 在编译向该请求提供服务所需资源的过程中出现错误.请检查下列特定错误详细信息并适当地修改源代码. 编译器错误消息: CS0042: 创建调试信息文件“ ...