Codeforces Round #787 (Div. 3)-F
题目
解题思路
这道题类似于天梯赛的送外卖题,但是又有区别,对于天梯赛那道题就从终点往前遍历即可,但是在此题中存在一个问题,因为不确定边与边之间的关系,所以没有办法直接搜索路径。这里只能通过遍历的方式来完成,对于一个点,我们考虑他是会被访问两次,还是访问一次,当然这个过程需要借助DFS实现。
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define rep(i,s,n) for(int i=s;i<n;i++)
const int MOD=1e9+7;
const int maxN=5e3+1;
const int INF=2e9;
const int MB=20;
vector<vector<int>> g;// 存储边
vector<bool> good; //只行一次的边
vector<bool> todo; //需要走两次的边
void dfs(int u,int p=-1)
{
for (auto &v:g[u])
{
if (v!=p)
{
dfs(v,u);
if (todo[v]==true)
todo[u]=true;
if (good[v]==true)
good[u]=true;
}
}
}
void solve()
{
int n,k;
cin>>n>>k;//读入点的个数和要去的点的个数
int x,y;
cin>>x>>y;//读入起始点和终止点
g.clear();
g.resize(n+1);
good.clear();
todo.clear();
good.resize(n+1,false);
todo.resize(n+1,false);
good[y]=true;
rep(i,0,k)
{
int _;
cin>>_;
todo[_]=true;
}
rep(i,0,n-1)
{
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(x);
int ans=0;
rep(i,1,n+1)
{
if (i==x)
continue;
if (good[i]==true)
ans++;
else if (todo[i]==true)
ans+=2;
}
cout<<ans<<"\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll n;
cin>> n;
while (n--)
{
solve();
}
system("pause");
return 0;
}