E1. Escape The Maze (easy version)

Codeforces Round #756 div3
date:2021/11/28

题目大意:

在一棵有根无向树中玩游戏,位于根节点 1 的 vlad 能否避开朋友们的阻拦到达任意根节点;
朋友们位于树上不同的结点上;
阻拦:他们同时移动,若在同一顶点相遇,或先vlad到达他要到达的结点,即半路拦截;

思路

参考思路
假设朋友所在的点为被tag的点;

通过观察可以发现,存在一个叶子结点使得根节点到它的距离,小于所有tag结点到它的最小距离;
那么就为 yes;

另一种思路就是,对于根节点要经过的点比较深度(等价根节点到该节点的距离)与 所有tag到该结点的 d i s m i n dis_{min} dismin;若深度大于 d i s m i n dis_{min} dismin,则此路不同,一直比较到根节点到达叶子节点,若到达不了即输出no,否则输出yes。详细代码解释qwq;

code

// Problem: E1. Escape The Maze (easy version)
// Contest: Codeforces - Codeforces Round #756 (Div. 3)
// URL: https://codeforces.com/contest/1611/problem/E1
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define _orz ios::sync_with_stdio(false),cin.tie(0)
#define mem(str,num) memset(str,num,sizeof(str))
#define forr(i,a,b) for(int i = a;i <= b;i++)
#define forn(i,n) for(int i = 0; i < n; i++)
#define all(a) (a.begin(),a.end())
#define dbg() cout << "0k!" << endl;
//#define _DEBUG
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 2e5+10;
const ll MOD = 1e9+7;
bool tag[N];
vector<int> e[N];
int d[N],dis[N],ok;
int n,k;
void dfs(int u ,int fa){
    
    
	if(tag[u]){
    
    
		dis[u] = 0;
		return;
	}
	for(auto it:e[u]){
    
    
		if(it == fa) continue;
		d[it] = d[u]+1;
		dfs(it,u);// 从下往上搜;
		dis[u] = min(dis[u],dis[it]+1); // 找tag点到u的最小距离;
	}
}

void dfs1(int u,int fa){
    
    
	if(d[u] >= dis[u]) return; // 深度大于距离 就放弃这条路
	if(e[u].size() == 1 && u != 1) ok = 1; // 到达叶子结点惹;
	for(auto it:e[u]){
    
    
		if(it == fa) continue;
		dfs1(it,u);
	}
}

void init(){
    
    
	ok = 0;
	forr(i,0,n) e[i].clear(),dis[i] = inf,d[i] = 0,tag[i] = 0;
}

void so1ve(){
    
    
	cin >> n >> k;
	init();
	while(k--){
    
    
		int x; cin >> x;
		tag[x] = 1;
	}
	forr(i,1,n-1){
    
    
		int u,v;cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	d[1] = 0;
	dfs(1,0);
	dfs1(1,0);
	
	if(ok) puts("yes");
	else	puts("no");

}
int main()
{
    
    
#ifdef _DEBUG
    //freopen("input.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    int t; cin >> t;
    while(t--) so1ve();
    return 0;
}

如有错误希望指出!!!
orz

D2的话就是在dfs1的基础上更改:

int dfs2(int u,int fa){
    
    
	int ret = 0;
	// 当u可以拦截时就++,表明存在一个tag拦截了vald;!!
	if(d[u] >= dis[u]){
    
    
		return 1;
	}
	for(auto it:e[u]){
    
    
		if(it == fa) continue;
		ret += dfs2(it,u);
	}
	return ret;
}

猜你喜欢

转载自blog.csdn.net/qq_51687628/article/details/121589127