牛客 美团编程真题 病毒传播 基础bfs暴力瞎搞

题目描述

给出一个图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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值