ZOJ-3811-Untrusted Patrol 解题报告

       裸BFS的题,网络赛的时候没做出来,事后才想通干掉。哭瞎。题意:在一个生产保健饮料的工厂仓库中有N个地点放了饮料,N个地点之间有M个通道。老板雇了保安夜晚来巡逻每一个存放饮料的地点。但是老板比较多疑,他在K个地点中装了传感器,由于内存限制,传感器只能显示人第一次到达该地点的时间。如果情况不安全的话,那么说明可能有另外的人进来了导致传感器记录的顺序不正常,就像是有人会穿墙或者传送之类的魔法一样。现在,需要你根据传感器的记录情况来判断情况是否安全,如果情况安全且保安能够顺利巡逻到存放饮料的每个点的话输出“Yes”,否则的话输出“No”。


       我的解题思路:首先根据题意可以判断出这个由N个点M条边构成的无向图必须每两个点都能够连通,否则的话说明保安不能够巡逻每一个存放饮料的地点。然后我们根据保安必须要对每一个地点进行巡逻可以知道每个传感器都必须要记录到信息。两个“Yes”前提条件有了,现在就考虑判断顺序的事了。假设保安以第一个记录信息的传感器地点为起点,然后从这个点开始进行BFS,不继续进行BFS的条件是当前地点为安装了传感器的地点,否则的话继续BFS。接下来我们开始第二个传感器点的BFS,当然有个前提条件是在前面的点的BFS中我们必须搜索到了这个传感器点,否则说明正常情况下没办法按照当前传感器记录的顺序进行巡逻。然后依次类推。每个传感器的点都能由更早记录信息的传感器的点BFS到,那么最后我们在判断一下是否每个存放饮料的点都已经走过了,也就是判断第一个前提条件。判断后就能确定答案了。


       我的解题代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

#define N 100002

bool vis[N];        //判断该点是否走过
bool isk[N];        //判断该点是否为传感器点
vector <int> e[N];  //邻接表存图
int s[N];           //存储记录信息的传感器的顺序
int n, m, k;
int kn;             //成功记录信息的传感器的数量

void InitRead();    //初始化输入

void DataProcess(); //数据处理

void Bfs(int x);    //从点x开始BFS

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        InitRead();
        DataProcess();
    }
    return 0;
}

void InitRead()
{
    int a, b;
    memset(isk, false, sizeof(isk));
    memset(vis, false, sizeof(vis));
    scanf("%d %d %d", &n, &m, &k);
    for (int i=0; i<k; ++i)
    {
        scanf("%d", &a);
    }
    for (int i=0; i<=n; ++i)
    {
        e[i].clear();
    }
    for (int i=0; i<m; ++i)
    {
        scanf("%d %d", &a, &b);
        e[a].push_back(b);
        e[b].push_back(a);
    }
    scanf("%d", &kn);
    for (int i=0; i<kn; ++i)
    {
        scanf("%d", &s[i]);
        isk[s[i]] = true;
    }
    return;
}

void DataProcess()
{
    if (kn != k)        //成功记录信息的传感器数量与传感器数量不一样
    {
        puts("No");
        return;
    }
    vis[s[0]] = true;
    for (int i=0; i<kn; ++i)
    {
        if (!vis[s[i]])     //如果通过前面的传感器点搜索不到该传感器点
        {
            puts("No");
            return;
        }
        Bfs(s[i]);
    }
    for (int i=1; i<=n; ++i)    //判断是否每个点都能走到
    {
        if (!vis[i])
        {
            puts("No");
            return;
        }
    }
    puts("Yes");
    return;
}

void Bfs(int x)
{
    queue <int> q;
    int a;
    q.push(x);
    while (!q.empty())
    {
        a = q.front();
        q.pop();
        for (int i=0; i<(int)e[a].size(); ++i)
        {
            if (!vis[e[a][i]])
            {
                vis[e[a][i]] = true;
                
                //如果该点是传感器点,该点不加入队列中
                if (isk[e[a][i]]) continue;
                q.push(e[a][i]);
            }
        }
    }
    return;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值