【HDU】3478Catch(二分图BFS判断+并差集)

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2401    Accepted Submission(s): 1161


 

Problem Description

A thief is running away!
We can consider the city where he locates as an undirected graph in which nodes stand for crosses and edges stand for streets. The crosses are labeled from 0 to N–1.
The tricky thief starts his escaping from cross S. Each moment he moves to an adjacent cross. More exactly, assume he is at cross u at the moment t. He may appear at cross v at moment t + 1 if and only if there is a street between cross u and cross v. Notice that he may not stay at the same cross in two consecutive moment.
The cops want to know if there’s some moment at which it’s possible for the thief to appear at any cross in the city.

 

 

Input

The input contains multiple test cases:
In the first line of the input there’s an integer T which is the number of test cases. Then the description of T test cases will be given.
For any test case, the first line contains three integers N (≤ 100 000), M (≤ 500 000), and S. N is the number of crosses. M is the number of streets and S is the index of the cross where the thief starts his escaping.
For the next M lines, there will be 2 integers u and v in each line (0 ≤ u, v < N). It means there’s an undirected street between cross u and cross v.
 

 

 

Output

For each test case, output one line to tell if there’s a moment that it’s possible for the thief to appear at any cross. Look at the sample output for output format.
 

 

 

Sample Input

 

2 3 3 0 0 1 0 2 1 2 2 1 0 0 1

 

 

Sample Output

 
Case 1: YES Case 2: NO

Hint

For the first case, just look at the table below. (YES means the thief may appear at the cross at that moment)

For the second input, at any moment, there’s at least one cross that the thief can’t reach.

 

 

Source

2010 ACM-ICPC Multi-University Training Contest(5)——Host by BJTU

 

 

Recommend

zhengfeng   |   We have carefully selected several similar problems for you:  3486 3485 3484 3483 3482 

 

 

Statistic | Submit | Discuss | Note

 

题目大意:现在有一个逃跑的小偷,先给出一个城市的N个节点和M条边,问你是否有某个时刻*这个小偷可以站在这个城市的任意一个点,也就是在任意时刻他可能站在从0~N的任意一个节点上,

思路:这个题目我分为二分图的判定,也就是说,如果这个图是二分图,那么一定不存在这样的时刻满足题意,因为二分图时某个时刻一定在两个节点集合的任意一个中,

一开始看网上大神的解释还要说这个图是联通的,其实是有这个必要的,因为如果这个图本来就有两个联通块,那这个图也一定不存在满足题意的时刻,但是这个题目貌似不需要,去掉代码中的判断连通性后也能过,

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=100000+10;
const int maxm=500000+10;

int n,m,s;
vector<int >G[maxn];
int color[maxn];
int fa[maxn];
int findset(int x)
{
    if(fa[x]==-1) return x;
    return fa[x]=findset(fa[x]);
}

bool bipaetite(int u) //从起点开始判断是否为二分图
{
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        if(color[u]==color[v]) return false;
        if(color[v]==0)
        {
            color[v]=3-color[u];
            if(!bipaetite(v)) return false;
        }
    }
    return true;
}

int main()
{
    int ti;scanf("%d",&ti);
    for(int kase=1;kase<=ti;kase++)
    {
        scanf("%d%d%d",&n,&m,&s);
        for(int i=0;i<n;i++) G[i].clear();
        memset(color,0,sizeof(color));
        memset(fa,-1,sizeof(fa));

        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
            u=findset(u),v=findset(v);
            if(u!=v)
                fa[u]=v;
        }

        int cnt=0;
        for(int i=0;i<n;i++) if(findset(i)==i) cnt++; //判断连通性,有几个联通块
        if(cnt>1)
        {
            printf("Case %d: NO\n",kase);
            continue;
        }

        color[s]=1;
        if(bipaetite(s)) // 判断是不是二分图,若果是则一定不存在这样的时刻
        {
            printf("Case %d: NO\n",kase);
        }
        else
        {
            printf("Case %d: YES\n",kase);
        }
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值