Edge to the Root


Time Limit: 1 Second      Memory Limit: 131072 KB

Given a tree with n vertices, we want to add an edge between vertex 1 and vertex x, so that the sum of d(1, v) for all vertices v in the tree is minimized, where d(u, v) is the minimum number of edges needed to pass from vertex u to vertex v. Do you know which vertex x we should choose?

Recall that a tree is an undirected connected graph with n vertices and n - 1 edges.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains an integer n (1 ≤ n ≤ 2 × 105), indicating the number of vertices in the tree.

Each of the following n - 1 lines contains two integers u and v (1 ≤ u, vn), indicating that there is an edge between vertex u and v in the tree.

It is guaranteed that the given graph is a tree, and the sum of n over all test cases does not exceed 5 × 105. As the stack space of the online judge system is not very large, the maximum depth of the input tree is limited to about 3 × 104.

We kindly remind you that this problem contains large I/O file, so it's recommended to use a faster I/O method. For example, you can use scanf/printf instead of cin/cout in C++.

Output

For each test case, output a single integer indicating the minimum sum of d(1, v) for all vertices v in the tree (NOT the vertex x you choose).

Sample Input

2
6
1 2
2 3
3 4
3 5
3 6
3
1 2
2 3

Sample Output

8
2

Hint

For the first test case, if we choose x = 3, we will have

d(1, 1) + d(1, 2) + d(1, 3) + d(1, 4) + d(1, 5) + d(1, 6) = 0 + 1 + 1 + 2 + 2 + 2 = 8

It's easy to prove that this is the smallest sum we can achieve.

【分析】给你一棵树,1节点为根。现在在除1号节点外任选一个节点与1节点连一条边,使得其他所有节点到一号节点的距离之和最小,求这个最小的距离之和。

首先咱想一个暴力的方法。直接枚举每一个节点U,使其与1号节点连边,那么U节点及其子树的距离都会被改变,改变值为dis[u]-1(dis[u]=dep[u]-1).再从1节点到U节点引一条路径,路径上的点及其子树的距离也会被改变,如果该路径上一个节点V的距离改变,那么该节点的所有子树(不包括该路径上的V的儿子节点及其子树)都会被改变,而且改变的差值都是一样的。现在我们就来分析一下哪些点会被更新。记录每一个节点的深度,dep[1]=1.比如dep[u]=6,即1-->2-->3-->4-->5-->6,当加一条边1-->6,则5,6节点及他俩的子树都会被改变,注意这里的路径上的节点都可能有子树,而且受5号节点影响的子树不包括6号节点(前面已说明)。

我们从6节点向上找到最后一个距离会被改变的节点,发现是5节点。而如果在6节点后面再接上7节点呢?可以发现还是5节点,然后再在纸上画几个发现:设向上最后一个被修改的节点为x,则dep[x]=dep[u]/2+2.(U为当前枚举的节点)。再看上边这个例子。5,6节点及其子树将被改变,对于6节点及其子树,改变值为(dis[6]-1)*sz[6],5节点及其子树:(dis[5]-1)*(sz[5]-sz[6]),合并得到 总改变值为2*(sz[5]+sz[6]),推广后,对于当前枚举节点dis是奇数的,差值为(2*(sz[u]+sz[fa[u]]+sz[fa[fa[u]]]...+sz[x]))而且可以推出当前节点dis为偶数时(dep为奇数),改变值为(2*(sz[u]+sz[fa[u]]+sz[fa[fa[u]]]...+sz[x])-sz[x]).号公式出来了,现在问题是怎么找这个x节点。嘻嘻,很简单,倍增记录祖先就行了,然后还得记录子树大小前缀和。

#include <bits/stdc++.h>
#define inf 1000000000
#define met(a,b) memset(a,b,sizeof a)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define mp make_pair
typedef long long ll;
using namespace std;
const int N = 2e5+;
const int M = 4e2+;
const ll mod = 1e9+;
int n,m,k;
ll ans,sz[N],sum[N],pre;
int fa[N][],dep[N];
vector<int>edg[N];
void dfs1(int u,int f){
sz[u]=;
fa[u][]=f;
dep[u]=dep[f]+;
for(int i=;i<;i++){
fa[u][i]=fa[fa[u][i-]][i-];
}
for(int i=;i<edg[u].size();i++){
int v=edg[u][i];
if(v==f)continue;
dfs1(v,u);
sz[u]+=sz[v];
}
pre+=dep[u]-;
}
void dfs2(int u,int f){
sum[u]=sum[f]+sz[u];
for(int i=;i<edg[u].size();i++){
int v=edg[u][i];
if(v==f)continue;
dfs2(v,u);
}
}
int main() {
int op,u,v,x,y;
scanf("%d",&op);
while(op--){
pre=;
met(fa,);
for(int i=;i<N;i++){
edg[i].clear();
sum[i]=;
}
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
edg[u].pb(v);
edg[v].pb(u);
}
dep[]=;
dfs1(,);
dfs2(,);
ans=pre;
for(int i=;i<=n;i++){
int d=dep[i];
int x=d/+;
if(d==||d==)continue;
u=i;
for(int j=;j>=;j--){
if(dep[fa[u][j]]<x)continue;
else if(dep[fa[u][j]]>x)u=fa[u][j];
else {
u=fa[u][j];
break;
}
}
if(d&){
v=fa[u][];
ll ret=*(sum[i]-sum[v])-sz[u];
ans=min(ans,pre-ret);
}
else {
v=fa[u][];
ll ret=*(sum[i]-sum[v]);
ans=min(ans,pre-ret);
}
}
printf("%lld\n",ans);
}
return ;
}

ZOJ 3949 Edge to the Root(想法)(倍增)的更多相关文章

  1. ZOJ 3949 Edge to the Root( 树形dp)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3949 题解:树dp真的很直觉,或者说dp真的很直觉.就上周末比赛时其实前一 ...

  2. ZOJ 3949 Edge to the Root(树形DP)

    [题目链接] http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3949 [题目大意] 给出一棵根为1的树,每条边边长为1,请你 ...

  3. ZOJ 3949 Edge to the Root

    题意: 在一棵树中,可以从根节点往其他节点加一条边,使得根节点到其他所有节点的距离和最小,输出最小的距离和. 思路: 我们考虑在加的一条边为$1 \to v$,那么在树上从$1 \to v$的路径上, ...

  4. 树dp...吧 ZOJ 3949

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5568 Edge to the Root Time Limit: 1 Secon ...

  5. POJ 3100 &amp; ZOJ 2818 &amp; HDU 2740 Root of the Problem(数学)

    题目链接: POJ:id=3100" style="font-size:18px">http://poj.org/problem? id=3100 ZOJ:http ...

  6. 【Codeforces827D/CF827D】Best Edge Weight(最小生成树性质+倍增/树链剖分+线段树)

    题目 Codeforces827D 分析 倍增神题--(感谢T*C神犇给我讲qwq) 这道题需要考虑最小生成树的性质.首先随便求出一棵最小生成树,把树边和非树边分开处理. 首先,对于非树边\((u,v ...

  7. ZOJ 3949 (17th 浙大校赛 B题,树型DP)

    题目链接  The 17th Zhejiang University Programming Contest Problem B 题意  给定一棵树,现在要加一条连接$1$(根结点)和$x$的边,求加 ...

  8. ZOJ 2048(Prim 或者 Kruskal)

    Highways Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge The island nation of F ...

  9. [HNOI 2015]开店

    Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...

随机推荐

  1. 「6月雅礼集训 2017 Day10」quote

    [题目大意] 一个合法的引号序列是空串:如果引号序列合法,那么在两边加上同一个引号也合法:或是把两个合法的引号序列拼起来也是合法的. 求长度为$n$,字符集大小为$k$的合法引号序列的个数.多组数据. ...

  2. [BZOJ1076][SCOI2008]奖励关解题报告|状压DP

    你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里,系统将依次随机抛出k次宝物,每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝物以后也不能再吃). 宝 ...

  3. Spring 路由地址的基本使用

    1.下面是spring的使用基本框架连接 https://www.cnblogs.com/HD/p/4103239.html

  4. ajax中datatype的json和jsonp

     前言: 说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域 ...

  5. list互转datatable 支持Nullable转换

    /// <summary> /// list转datatable /// </summary> /// <param name="list">& ...

  6. 【Mysql优化】索引覆盖

    索引覆盖 是指 如果查询的列恰好是索引的一部分,那么查询只需要在索引文件上进行,不需要回行到磁盘再找数据.这种查询速度非常快,称为”索引覆盖”,比平时的查询少一次到磁盘读数据的操作.(索引正好覆盖到查 ...

  7. web服务器和数据库服务器不在一台机器上

    把localhost改成数据库所在的IP就行了. $link=mysql_connect( "202.195.246.202 ", "root ", " ...

  8. sublime在搜索的时候排除js文件

    代码审计的时候sublime是一个神器.所以.... Ctrl + Shift + F /home/i3ekr/Desktop/coding/phpcms,*.php 这样就可以直接搜索所有的php文 ...

  9. [Leetcode Week15]Populating Next Right Pointers in Each Node

    Populating Next Right Pointers in Each Node 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/populati ...

  10. hadoop InputFormat 类别

    FileInputFormat是所有使用文件作为数据源的InputFormat的积累.它提供两个功能:一个是定义哪些文件包含在一个作业的输入中:一个为输入文件生成分片的实现.自动将作业分块 作业分块大 ...