您的位置:首页 > 其它

【重点】Codeforces Round #364 (Div. 2)

2016-07-23 16:35 239 查看
唉,有一场很好加分的场没加多少

确实如出题人所说,用各个难度梯度的简单题出了,但是只能说自己太菜了。

前40min ABC 都过了,都是乱搞题

D 推公式 推了好久都是错的,可能是半夜脑子不好使,居然在第二天发现推的公式对了大半,最后输出结果产生了问题,也是醉了。

E 主要想讲一下E, 赛后看了看hx的代码,觉得好厉害啊。 按这种想法写出来的代码简单,但是我不知道证明这种想法的正确性,模模糊糊的感觉应该是对的

题意:

给你一棵树 包含n个点,然后给你 2*k 个点, 要你从这2k个点中 选出k对点,使得k对点 距离和 最大。

n<2*1e5 k<=n/2

然后我想了一下, 点边都是10W,不太可能直接跑出来。

想一下 在一棵树中,从2*k中选出k对,求出每一对u,v 之间的距离。那么u,v必然不能在同一棵子树中,因为 假如在另外一颗子树中选出x,y 这样的话dis(u,v)+dis(x,y) < dis(u,x)+dis(v,y) 或者 dis(u,y)+dis(v,x)

照这个想法,我们只要选出一个root 建树,然后我们保证 root 的每一子树的所有被标记的节点数目 都 <= k ,因为如果某个子树的标记节点数目>k,那么就肯定有点无法和其他子树节点匹配到。

但是我并不知道 这个root 是不是一定存在,讲道理是应该存在的。

然后建好树,我们就只需要跑出来每个标记节点到root的距离,相加就好

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#define mem(a) memset(a,0,sizeof(a))
#define pfn printf("\n")
#define ll __int64
#define pfd(a) printf("%d\n",a)
#define pf2d(a,b) printf("%d %d\n",a,b)
#define pf3d(a,b,c) printf("%d %d %d\n",a,b,c)
#define pfs(a) printf("%s\n",a)
#define sfd(a) scanf("%d",&a)
#define sf2d(a,b) scanf("%d%d",&a,&b)
#define sf3d(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define sf    scanf
#define pf    printf
#define fr(i,n) for(int i=0;i<n;i++)
const double PI = acos(-1.0);
const double e = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
bool cmpbig(int a,int b){return a>b;}
bool cmpsmall(int a,int b){return a<b;}
using namespace std;

#define clean(a) memset(a, 0, sizeof(a))

const int maxn = 200100;
int n, k, root, w[maxn], size[maxn];
ll len[maxn];
vector<int> g[maxn];

void dfs(int t, int fa){
size[t] = w[t];
bool flag = 1;
for(int i=0;i<g[t].size();i++){
int v=g[t][i];
if(v != fa){
dfs(v, t);
size[t] += size[v];
if(size[v] > k) flag = 0;
}
}
if(2 * k - size[t] > k) flag = 0;
if(flag) root = t;
}
int dir[maxn];
void DFS(int t, int fa){
for(int i=0;i<g[t].size();i++){
int v=g[t][i];
if(v != fa){
dir[v]=dir[t]+1;
DFS(v, t);
}
}
}

int main(){
//freopen("1.txt","r",stdin);
scanf("%d%d", &n, &k);
for(int i = 1; i <= 2 * k; ++i){
int u;
scanf("%d", &u);
w[u]++;
}
for(int i = 1; i < n; ++i){
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v), g[v].push_back(u);
}
dfs(1, 0);
//  printf("root=%d\n",root);
dir[root]=0;
DFS(root, 0);
__int64 ans=0;
for(int i=1;i<=n;i++)
if(w[i]>0){
ans+=dir[i];
}
printf("%I64d\n", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: