Infected Tree

Byteland is a beautiful land known because of its beautiful trees.

Misha has found a binary tree with nn vertices, numbered from 11 to nn. A binary tree is an acyclic connected bidirectional graph containing nn vertices and n−1n−1 edges. Each vertex has a degree at most 33, whereas the root is the vertex with the number 11 and it has a degree at most 22.

Unfortunately, the root got infected.

The following process happens nn times:

  • Misha either chooses a non-infected (and not deleted) vertex and deletes it with all edges which have an end in this vertex or just does nothing.
  • Then, the infection spreads to each vertex that is connected by an edge to an already infected vertex (all already infected vertices remain infected).

As Misha does not have much time to think, please tell him what is the maximum number of vertices he can save from the infection (note that deleted vertices are not counted as saved).

Input

There are several test cases in the input data. The first line contains a single integer tt (1≤t≤50001≤t≤5000) — the number of test cases. This is followed by the test cases description.

The first line of each test case contains one integer nn (2≤n≤3⋅1052≤n≤3⋅105) — the number of vertices of the tree.

The ii-th of the following n−1n−1 lines in the test case contains two positive integers uiui and vivi (1≤ui,vi≤n1≤ui,vi≤n), meaning that there exists an edge between them in the graph.

It is guaranteed that the graph is a binary tree rooted at 11. It is also guaranteed that the sum of nn over all test cases won't exceed 3⋅1053⋅105.

Output

For each test case, output the maximum number of vertices Misha can save.

Example

input

Copy

4
2
1 2
4
1 2
2 3
2 4
7
1 2
1 5
2 3
2 4
5 6
5 7
15
1 2
2 3
3 4
4 5
4 6
3 7
2 8
1 9
9 10
9 11
10 12
10 13
11 14
11 15

output

Copy

0
2
2
10

Note

In the first test case, the only possible action is to delete vertex 22, after which we save 00 vertices in total.

In the second test case, if we delete vertex 22, we can save vertices 33 and 44.

 

 

 

 

 

思路:这个是“砍树”问题。所以我们这里用dp写(也叫树形dp)。因为用到树了,所以用递归。下面我们设 f 为当前节点生病仍能产生多少贡献,sz数组表示当前节点的大小。

递归:递归之上为初始化,递归之下为展开,不断“相加”,类似与for循环。

用二维vector存图。

先算以前才能算现在的,即先算出子节点(子树),才能处理当前节点。//s要求是紧连的两个节点,求完s的全部才算是一颗整树(完整子树)。

完整代码:

#include <bits/stdc++.h>

using namespace std;

#define int long long
const int mod=1e9+7;

const int N=3e5+10;
int f[N],sz[N];
vector<int>v[N];

void dfs(int now,int fa)
{
    sz[now]=1,f[now]=0;
    int s=0;
    for(auto to:v[now])
    {
        if(to!=fa)
        {
            dfs(to,now);
            s+=f[to];//代表两个子节点(是生病状态下)产生的贡献
            sz[now]+=sz[to];//f[now]代表生病节点产生的贡献
        }
    }
    
    for(auto to:v[now])
    {
        if(to!=fa)
            f[now]=max(f[now],s-f[to]+sz[to]-1);
    }
}

void solve()
{
    int n;
    cin>>n;
    //memset(f,0,(n+5)*sizeof(int));
    //memset(sz,0,(n+5)*sizeof(int));
    for(int i=1;i<=n;i++)v[i].clear();
    
    for(int i=1;i<=n-1;i++)
    {
        int a,b;
        cin>>a>>b;
        v[a].push_back(b);
        v[b].push_back(a);
    }
    dfs(1,0);
    cout<<f[1]<<endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int t;
    cin>>t;
    while(t--)
    {
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值