ZOJ3811 Untrusted Patrol (2014年牡丹江赛区网络赛C题)

1.题目描述:点击打开链接

2.解题思路:本题利用BFS+并查集解决。题意要求寻找输入的访问次序是否可行,而且所有结点都要访问到,因此,如果一开始整个图是不连通的,自然要输出No,连通性可以用并查集来判断。如果图连通,那么看L和K的关系,如果L<K,说明有的传感器一直都没有收到第一次访问的信息,即这个结点始终没有被访问过,也是直接输出No,否则的话,我们开始寻找第一个要访问的仓库。


如果访问顺序是可行的,那么第一个仓库是谁并不重要,不妨就把收集到的第一个传感器信号所在的结点作为第一个访问的仓库,接下来我们可以利用BFS将所有相邻的带有传感器的结点给标记了,即一开始将有传感器的结点标记为1,在BFS中将他们置零。这样,如果下一个输入的传感器结点依然是1的话,说明访问次序是不可能的。否则,继续对新的结点进行BFS。


为什么可以这么做呢?因为题目中告诉我们传感器只能接收第一次访问的信息,那么我们从u出发(u是一个带有传感器的结点),访问下一个有传感器的结点v,此时u,v的传感器都被关闭了,再通过u去访问另一个和他相邻的传感器结点w,这样下来,只要和u相邻的传感器,都可以按照任意顺序访问到。反过来说,如果某个传感器v仍然是1,那么它必然和u是不相邻的传感器,不可能从u直接就访问到了v。由此证明了BFS做法的正确性。

3.代码:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<functional>
using namespace std;

#define me(s)  memset(s,0,sizeof(s))
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair <int, int> P;


const int N=100000+5;

int vis[N],t[N];
int p[N];
vector<int>g[N];

int find(int x)
{
    return p[x]==x?x:p[x]=find(p[x]);
}

void bfs(int u)
{
    vis[u]=1;
    t[u]=0;
    queue<int>q;
    q.push(u);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        int len=g[u].size();
        for(int i=0;i<len;i++)
        {
            int v=g[u][i];
            if(t[v]||vis[v])
            {
                t[v]=0;vis[v]=1;continue;
            }
            vis[v]=1;
            q.push(v);
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,k,l;
        me(t);me(vis);me(p);
        for(int i=0;i<N;i++)g[i].clear();
        scanf("%d%d%d",&n,&m,&k);
        int x;
        for(int i=0;i<k;i++)
        {
            scanf("%d",&x);
            t[x]=1;   //将含有传感器的结点标记为1
        }
        int u,v;
        int cnt=n;
        for(int i=1;i<=n;i++)p[i]=i;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
            int x=find(u),y=find(v);
            if(x!=y)
            {
                p[x]=y;
                cnt--;
            }
        }
        int flag=1;
        if(cnt>1)flag=0;//如果连通分量的数目大于1,说明整个图不连通
        scanf("%d",&l);
        if(l<k)flag=0;  //如果收到的传感器个数小于K,说明有的结点根本没有去访问
        for(int i=0;i<l;i++)
        {
            scanf("%d",&x);
            if(flag==0||(t[x]&&i)) //如果不是头结点且t[x]仍然是1,说明该访问次序是不可能的
            {
                flag=0;continue;
            }
            bfs(x);  //否则,对该结点进行BFS,将相邻的传感器结点标记为0
        }
        printf("%s\n",flag?"Yes":"No");
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值