码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-08-18 12:03:08      阅读:109      评论:0      收藏:0      [点我收藏+]

标签:bfs   连通性   结点的访问次序   并查集   

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");
    }
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:bfs   连通性   结点的访问次序   并查集   

原文地址:http://blog.csdn.net/u014800748/article/details/47747867

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!