码迷,mamicode.com
首页 > 其他好文 > 详细

cf 700 B Connecting Universities

时间:2016-08-18 01:06:09      阅读:292      评论:0      收藏:0      [点我收藏+]

标签:

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

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

技术分享
  1 #include <algorithm>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <string>
  5 #include <queue>
  6 #include <map>
  7 #include <set>
  8 #include <stack>
  9 #include <ctime>
 10 #include <cmath>
 11 #include <iostream>
 12 #include <assert.h>
 13 #pragma comment(linker, "/STACK:102400000,102400000")
 14 #define max(a, b) ((a) > (b) ? (a) : (b))
 15 #define min(a, b) ((a) < (b) ? (a) : (b))
 16 #define mp std :: make_pair
 17 #define st first
 18 #define nd second
 19 #define keyn (root->ch[1]->ch[0])
 20 #define lson (u << 1)
 21 #define rson (u << 1 | 1)
 22 #define pii std :: pair<int, int>
 23 #define pll pair<ll, ll>
 24 #define pb push_back
 25 #define type(x) __typeof(x.begin())
 26 #define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++)
 27 #define FOR(i, s, t) for(int i = (s); i <= (t); i++)
 28 #define ROF(i, t, s) for(int i = (t); i >= (s); i--)
 29 #define dbg(x) std::cout << x << std::endl
 30 #define dbg2(x, y) std::cout << x << " " << y << std::endl
 31 #define clr(x, i) memset(x, (i), sizeof(x))
 32 #define maximize(x, y) x = max((x), (y))
 33 #define minimize(x, y) x = min((x), (y))
 34 using namespace std;
 35 typedef long long ll;
 36 const int int_inf = 0x3f3f3f3f;
 37 const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
 38 const int INT_INF = (int)((1ll << 31) - 1);
 39 const double double_inf = 1e30;
 40 const double eps = 1e-14;
 41 typedef unsigned long long ul;
 42 typedef unsigned int ui;
 43 inline int readint(){
 44     int x;
 45     scanf("%d", &x);
 46     return x;
 47 }
 48 inline int readstr(char *s){
 49     scanf("%s", s);
 50     return strlen(s);
 51 }
 52 
 53 class cmpt{
 54 public:
 55     bool operator () (const int &x, const int &y) const{
 56         return x > y;
 57     }
 58 };
 59 
 60 int Rand(int x, int o){
 61     //if o set, return [1, x], else return [0, x - 1]
 62     if(!x) return 0;
 63     int tem = (int)((double)rand() / RAND_MAX * x) % x;
 64     return o ? tem + 1 : tem;
 65 }
 66 ll ll_rand(ll x, int o){
 67     if(!x) return 0;
 68     ll tem = (ll)((double)rand() / RAND_MAX * x) % x;
 69     return o ? tem + 1 : tem;
 70 }
 71 
 72 void data_gen(){
 73     srand(time(0));
 74     freopen("in.txt", "w", stdout);
 75     int kases = 40000;
 76     printf("%d\n", kases);
 77     while(kases--){
 78         ll sz = 1e18;
 79         printf("%lld\n", Rand(sz, 1));
 80     }
 81 }
 82 
 83 struct cmpx{
 84     bool operator () (int x, int y) { return x > y; }
 85 };
 86 const int maxn = 2e5 + 10;
 87 int n, k;
 88 bool np[maxn];
 89 struct E{
 90     int to, nex;
 91 }e[maxn << 1];
 92 int head[maxn], N;
 93 void addE(int x, int y){
 94     e[N].nex = head[x];
 95     e[N].to = y;
 96     head[x] = N++;
 97     e[N].nex = head[y];
 98     e[N].to = x;
 99     head[y] = N++;
100 }
101 int cnt[maxn];
102 void dfs1(int u, int fa){
103     cnt[u] = np[u];
104     for(int i = head[u]; ~i; i = e[i].nex){
105         int v = e[i].to;
106         if(v == fa) continue;
107         dfs1(v, u);
108         cnt[u] += cnt[v];
109     }
110 }
111 int rt;
112 bool flag;
113 void dfs2(int u, int fa){
114     if(flag) return;
115     int maxi = 0;
116     int tot = 0;
117     for(int i = head[u]; ~i; i = e[i].nex){
118         int v = e[i].to;
119         if(v == fa) continue;
120         maximize(maxi, cnt[v]);
121         tot += cnt[v];
122     }
123     if(np[u]) ++tot;
124     maximize(maxi, 2 * k - tot);
125     if(maxi <= k){
126         rt = u;
127         flag = 1;
128         return;
129     }
130     for(int i = head[u]; ~i; i = e[i].nex) if(e[i].to != fa) dfs2(e[i].to, u);
131 }
132 ll dfs3(int u, int fa, int d){
133     ll tem = 0;
134     if(np[u]) tem += d;
135     for(int i = head[u]; ~i; i = e[i].nex){
136         int v = e[i].to;
137         if(v == fa) continue;
138         tem += dfs3(v, u, d + 1);
139     }
140     return tem;
141 }
142 int main(){
143     //data_gen(); return 0;
144     //C(); return 0;
145     int debug = 0;
146     if(debug) freopen("in.txt", "r", stdin);
147     //freopen("out.txt", "w", stdout);
148     while(~scanf("%d", &n)){
149         k = readint();
150         clr(np, 0);
151         FOR(i, 1, 2 * k) np[readint()] = 1;
152         N = 0, clr(head, -1);
153         FOR(i, 2, n){
154             int x = readint(), y = readint();
155             addE(x, y);
156         }
157         dfs1(1, -1);
158         rt = 1;
159         flag = 0;
160         dfs2(1, -1);
161         ll ans = dfs3(rt, -1, 0);
162         printf("%lld\n", ans);
163     }
164     return 0;
165 }
code:

 

cf 700 B Connecting Universities

标签:

原文地址:http://www.cnblogs.com/astoninfer/p/5782447.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!