D 与 S
题目链接:D 与 S
题目描述:
\(S\)在追杀\(D\)。 现在,\(D\) 在一张有\(N\)点\(M\)边的无向图的\(1\)号点(顶点从\(1\)开始编号)。 每一秒\(S\)会剪掉与\(D\)相邻的一条边,然后\(D\)会走到一条没被剪掉的边的终点。有\(K\)个关键点,如果\(D\)到达了其中一个关键点,则\(D\)逃跑成功。\(S\)要尽可能地阻止\(D\)逃跑成功。 你需要回答:若都采用最优策略,\(D\)能不能逃跑成功。注意,如果\(D\)一开始就处在关键点,也算做他逃跑成功。
思路:根据题意可以看出,当一个点所连的点里面有不少于\(2\)关键点时,这个点也是关键点,所以我们可以使用类似拓扑排序的思想,将\(K\)个关键点加入队列,然后进行\(BFS\),如果一个点被访问了超过两次,说明它是关键点,将其也加入队列。最后只需要判断\(1\)号点是否是关键点即可。
时间复杂度:\(O(T\times M)\)
参考代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int T , n , u , v, m , k;
vector<vector<int>>graph(N);
queue<int> q;
int cnt[N], a, vis[N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> T;
while(T--){
cin >> n >> m >> k;
for(int i = 1 ; i <= k ; ++i){
cin >> a;
q.push(a);
vis[a] = true;
}
for(int i = 1 ; i <= m ; ++i){
cin >> u >> v;
graph[u].push_back(v);
graph[v].push_back(u);
}
while(!q.empty()){
int ver = q.front(); q.pop();
for(auto& v : graph[ver]){
++cnt[v];
if(!vis[v] && cnt[v] >= 2) q.push(v),vis[v] = true;
}
}
puts(vis[1] ? "yes" : "no");
for(int i = 1 ; i <= n ; ++i) graph[i].clear();
for(int i = 1 ; i <= n ; ++i) cnt[i] =0, vis[i] = false;
}
return 0;
}
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。