小明的宠物猫账账躲在了树上,小明来捕捉它。
树一共有 nnn 个节点,账账在根节点 xxx 处。每一秒钟,小明可以封锁一个节点(不可以为账账在的节点),然后账账可以移动到一个树上相邻的未被封锁的节点。若账账逃到了叶子,那么它就逃脱成功。
小明发现这样很有可能让账账逃跑。于是决定提前封锁一些节点。他想知道,他最少需要提前封锁多少节点,才可以不让账账成功逃脱。
输入格式
本题有 TTT 组测试数据。对于每组数据:
第一行一个数 nnn。
接下来 n−1n-1n−1 行,每行 u,vu,vu,v 表示树上一条边。
最后一行一个数 xxx 表示猫在的节点。
输出格式
对于每组数据输出一行表示答案。
样例
样例输入
1
7
1 2
2 4
2 5
1 3
3 6
3 7
1
样例输出
1
提示说明
对于样例数据,提前封禁 222 号点,就可以保证账账无法逃脱。
对于 10%10\%10% 的数据,2≤n≤202 \le n \le 202≤n≤20。
对于 40%40\%40% 的数据,2≤n≤50002 \le n \le 50002≤n≤5000。
对于 100%100\%100% 的数据,2≤n≤2000002 \le n \le 2000002≤n≤200000,1≤x≤n1\le x\le n1≤x≤n,1≤T≤51\le T\le 51≤T≤5。
解析
若某个子节点有两条可以逃跑的路线,就需要事先封堵一条。
对于叶子节点,可以直接逃脱。
递归计算每个节点可以逃跑的路线,对于多于一条的进行封堵,详见代码:
感谢 广州孩宝机器人的王淞老师 提供的修改意见
修改了原题解存在会输出-1的问题
#include<bits/stdc++.h>
using namespace std;
int t, n, x;
vector <int> g[200005];//邻接表存树
int dfs(int gf, int f) {
//叶子节点,可以逃脱,定义为2条路
if (g[f].size() == 1) return 2;
int ret = 0; //初始化可逃跑路线为0
for(int i = 0; i < g[f].size(); i++) { //递归每一个子节点
int s = g[f][i]; //子节点
if (s != gf) { //排除父节点
int t = dfs(f, s); //递归子节点的逃跑路线
if (t >= 2) { //如果子节点有两条以上可以逃跑的路线
ret++;//该子节点可以逃掉
}
}
}
return ret;//返回可逃跑路线
}
int main() {
cin >> t;
while(t--) {
cin >> n;
for(int i = 1; i < n; i++) { //邻接表存树
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
cin >> x; //根
cout << max(dfs(0, x) - 1, 0) << endl; //从根开始递归
for(int i = 1; i <= n; i++) { //清空邻接表
g[i].clear();
}
}
return 0;
}
823

被折叠的 条评论
为什么被折叠?



