题意:
给定一棵树,树苗定义为至少存在一个子节点并且子节点都是叶子,每次可以选择一颗树苗挂到某个节点下,求最小根节点数。
思路:
可以观察到挂到某个节点下,一定是挂到他的叶子结点,这样会对答案贡献减1,那么我们是不是可以把问题转化成最多的树苗数了?贡献就是树苗数-1,那我们考虑能不能从下往上尽量拆,遇到能拆的尽量拆,这样可以变成更多个树苗了。
// Problem: E. Buds Re-hanging
// Contest: Codeforces - Codeforces Global Round 16
// URL: https://codeforces.com/contest/1566/problem/E
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define x first
#define y second
typedef pair<int,int> pii;
const int N=200010;
vector<int>v[N];
int d[N];
int res;
int minv=1e9;
int idx;
vector<int>g[N];
int cnt=0;
bool st[N];
void dfs(int u,int fa){
st[u]=false;
int cnt=0;
for(auto j:v[u])
{
if(j==fa) continue;
dfs(j,u);
if(!st[j]){
cnt++;
}
}
if(!cnt){
if(u==1) {
++idx;
res+=1;
}
}
else
{
++idx;
st[u]=true;
res+=cnt;
}
}
int main()
{
int _;
cin>>_;
while(_--){
int n;
res=0;
cnt=0;
cin>>n;
idx=0;
for(int i=1;i<=n;i++) v[i].clear(),d[i]=0;
for(int i=0;i<n-1;i++){
int a,b;
cin>>a>>b;
v[a].push_back(b);
v[b].push_back(a);
}
dfs(1,-1);
// cout<<res<<endl;
// cout<<res<<" "<<cnt<<endl;
cout<<res-(idx-1)<<endl;
}
}
/**
* In every life we have some trouble
* When you worry you make it double
* Don't worry,be happy.
**/