题目
- 原题地址:E2. Escape The Maze (hard version)
 
- 题目编号:1611E2
 
- 目标算法:深搜(dfs)、最短路、动态规划(dp)
 
- 难度评分:1900
 
1.题目大意
- 基本的内容和 E1 一样,只有问题不同
 
- 上一篇题解的链接如下:
 
- 问在给定的朋友中,最少几人可以拦住小 V。
 
2.题目分析
- 在上一题的基础上:
- 输出为 YES 的情况无人可拦,输出 -1;
 
- 输出为 NO 的情况只需要选出:所有无人的叶子结点中,每个结点拦住小 V 的不同的朋友个数。
 
 
3.题目代码
#include 
#define MAX 200005
using namespace std;
const int INF = 0x3f3f3f3f;
vector e[MAX];
int dis[MAX], dp[MAX];
int ans = 0;
void dfs(int u, int pre)
{
    if(u != 1)
        dp[u] = dp[pre] + 1;
    for(int v: e[u])
        if(v!=pre)
            dfs(v, u);
}
void dfs2(int u, int pre)
{
    if(dis[u] == 0) return;
    int t = INF;
    for(int v: e[u])
    {
        if(v==pre) continue;
        dfs2(v, u);
        t = min(t, dis[v]);
    }
    dis[u] = t + 1;
}
bool dfs3(int u, int pre)
{
    if(dis[u]<=dp[u])
    {
        ans++;
        return 0;
    }
    if(e[u].size()==1&&u!=1) return 1;
    bool f = 0;
    for(int v: e[u])
        if(v!=pre)
            f |= dfs3(v, u);
    return f;
}
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int n, k;
        cin >> n >> k;
        for(int i=1;i<=n;i++)
        {
            dp[i] = 0;
            dis[i] = INF;
            e[i].clear();
        }
        for(int i=1;i<=k;i++)
        {
            int t;
            cin >> t;
            dis[t] = 0;
        }
        for(int i=1;i> u >> v;
            e[u].push_back(v);
            e[v].push_back(u);
        }
        dfs(1, 0);
        dfs2(1, 0);
        if(dfs3(1, 0))
            cout << -1 << endl;
        else
            cout << ans << endl;;
        ans = 0;
    }
}