题目描述
给出一个图G(V,E),图上有n个点,m条边,所有的边都是无向边。
最开始,也就是第0天的时候,这n个点中有一个点v感染了病毒,之后的每一天,凡是感染病毒的点都会向它的邻居点传播病毒。经过了t天之后,得到了感染病毒的点集S。要求找出第0天感染病毒的点v。如果v有很多不同的答案,把它们都找出来。
输入描述:
第一行两个数n,m,接下来有m行,每行两个数u,v,表示点u,v之间有一条无向边。接下来一行两个数k,t,其中k表示集合S的大小。最后一行k个数,集合S中的元素。输入的图可能有自环和重边,输入保证S中的数互不相同。(1≤n≤103,0≤m≤103,1≤t≤109,1≤u,v,k≤n,S中所有元素在区间[1,n])
输出描述:
输出一行,如果不存在这样的v,输出-1。
否则输出所有可能的v,按照从小到大的顺序输出,数字之间用空格隔开,不要在行末输出多余的空格。
示例1
输入
复制
4 3
3 2
1 2
1 4
3 2
4 2 1
输出
复制
4
说明
第0天,第1天,第2天感染病毒的点如图
- 注意看数据范围
n<=1000, m<=1000
, N 2 N^2 N2的复杂度足以 - 考虑
枚举
所有被感染点记为S
,对每个S
以她为根进行限定层数的bfs
每次bfs
都会得到一组点集points
,
用points
里的点和题目中的被感染点比较是否相同即可 - 由于
bfs
的复杂度是 O ( n ) O(n) O(n)的,枚举了n
次,所以总复杂度 O ( N 2 ) O(N^2) O(N2)
代码如下
#define debug
#ifdef debug
#include <time.h>
#endif
#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <math.h>
#define MAXN (1024)
#define ll long long int
#define INF (0x7f7f7f7f)
#define fori(lef, rig) for(int i=lef; i<=rig; i++)
#define forj(lef, rig) for(int j=lef; j<=rig; j++)
#define fork(lef, rig) for(int k=lef; k<=rig; k++)
#define QAQ (0)
using namespace std;
#define show(x...) \
do { \
cout << "\033[31;1m " << #x << " -> "; \
err(x); \
} while (0)
void err() { cout << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }
namespace FastIO{
char print_f[105];
void read() {}
void print() { putchar('\n'); }
template <typename T, typename... T2>
inline void read(T &x, T2 &... oth) {
x = 0;
char ch = getchar();
ll f = 1;
while (!isdigit(ch)) {
if (ch == '-') f *= -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - 48;
ch = getchar();
}
x *= f;
read(oth...);
}
template <typename T, typename... T2>
inline void print(T x, T2... oth) {
ll p3=-1;
if(x<0) putchar('-'), x=-x;
do{
print_f[++p3] = x%10 + 48;
} while(x/=10);
while(p3>=0) putchar(print_f[p3--]);
putchar(' ');
print(oth...);
}
} // namespace FastIO
using FastIO::print;
using FastIO::read;
int n, m, Q, K, die[MAXN], vis[MAXN], T, cas, x;
vector<int> G[MAXN];
struct Node {
int v, step;
} ;
int bfs(int s) { // 如果T轮后点集和题目给定的一致就返回true
memset(vis, false, sizeof(vis));
queue<Node> q;
vis[s] = true;
q.push({s, 0});
while(!q.empty()) {
Node now = q.front(); q.pop();
if(now.step > T) break; //只进行 T 轮 bfs
for(auto v : G[now.v])
if(!vis[v] && now.step+1<=T) { // 剪枝 减去所有越界的点
vis[v] = true;
q.push({v, now.step+1});
}
}
int ok = true;
for(int i=1; i<=n; i++) //和题目给定的点比对即可
ok = (ok && vis[i]==die[i]);
return ok;
}
signed main() {
#ifdef debug
freopen("test.txt", "r", stdin);
clock_t stime = clock();
#endif
read(n, m);
int u, v;
while(m--) {
read(u, v);
G[u].push_back(v);
G[v].push_back(u);
}
read(m, T);
for(int i=1; i<=m; i++) {
read(x);
die[x] = true; //记录所有题目给定的被感染的点
}
for(int i=1; i<=n; i++) //枚举每个点进行bfs
if(die[i] && bfs(i)) {
if(cas ++) printf(" ");
printf("%d", i);
}
printf("%s", cas ? "" : "-1");
#ifdef debug
clock_t etime = clock();
printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif
return 0;
}