题意:给你一颗树,问最少取几点并且得知其与未知点x的距离可以确定树中任意x是哪个节点。
思考:观察可知,对于叶子节点,其兄弟节点到父节点所在的路径上都有点被取到时,不用取它也可以知道具体是哪个点了。所以一开始我们先取全部的叶子节点,然后每个叶子节点向上dfs,遇见没走过的分支就可删去一个叶子节点的贡献了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pll pair<long long,long long>
#define INF 0x7fffffff
//const int mod=
//mt19937 rnd(std::chrono::system_clock::now().time_since_epoch().count());
//uniform_int_distribution<long long> dist(0, 100000);//随机数限定范围:dist(rnd);
const int maxn=200010;
int n,ans,vis[maxn];
vector<int> t[maxn],l;
map<int,int> mp;
void dfs(int x)
{
vis[x]=1;
if(t[x].size()>2)
{
ans--;
return;
}
for(auto i:t[x])
{
if(!vis[i]) dfs(i);
}
}
void solve()
{
ans=0;
l.resize(0);
mp.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
t[i].resize(0);
vis[i]=0;
}
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
t[x].push_back(y);
t[y].push_back(x);
mp[x]++,mp[y]++;
}
int flag=1;
for(auto i:mp)
{
if(i.second==1)
{
l.push_back(i.first);
ans++;
}
if(i.second>2) flag=0;
}
if(n==1)
{
puts("0");
return;
}
if(flag)
{
puts("1");
return;
}
for(int i=0;i<l.size();i++)
{
dfs(l[i]);
}
printf("%d\n",ans);
}
signed main()
{
int test=1;
scanf("%d",&test);getchar();
while(test--)
{
solve();
}
return 0;
}