拦截匪徒

【问题描述】

  某城市的地图是一个由N个点组成的无向图,每个点代表一个区。现在p区发生抢劫案,而警察为了截住劫匪须埋伏在一个劫匪必经区域。由于不知道劫匪会向哪个区逃窜,所以市长要求对于任意一个劫匪可能逃向的区j,找出一个可以拦截劫匪的区域k(k!=p,k!=j),即劫匪从p区逃向j区,必须经过k区。由于地区j可能为匪徒的老巢所在,所以警察希望能在路上拦截住土匪,而不是在j区抓获。

【输入格式】

  第一行N,p,接下来得为N*N的矩阵A,A[i][j]=1,表示i与j右路相连,A[i][j]=0则没有。

【输出格式】

  输出N-1行,输出警察应在哪个些置埋伏,按j=1、2、…p-1、p+1、…N的顺序输出,若有多点,由小到大顺序输出,如没有则输出No。

【输入样例】

5 1
0 1 1 0 0
1 0 1 1 0
1 1 0 0 0
0 1 0 0 1
0 0 0 1 0

【输出样例】

No
No
2
2 4

【数据范围】

1<=N,p<=300

这道题就是简单的暴力枚举,枚举每个点删除后能否到达目标点,就可以得到答案,但要注意一开始就不连通的情况(这就是我错的原因了)。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=305;
vector<int >g[maxn];
int n,m,vis[maxn];

void init()
{
    memset(vis,0,sizeof(vis));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        int x;
        scanf("%d",&x);
        if(x) g[i].push_back(j);
    }
}

void bfs(int y,int z)
{
    queue<int>q;
    q.push(m);
    vis[m]=1;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=0;i<g[x].size();i++)
        {
           int j=g[x][i];
           if(j==y) continue;
           if(vis[j])
           continue;
           vis[j]=1;
           q.push(j);
        }
    }
}
int main()
{
    freopen("catch.in","r",stdin);
    //freopen("catch.out","w",stdout);
    init();
    for(int i=1;i<=n;i++) if(i!=m)
    {
        memset(vis,0,sizeof(vis));
        bfs(m,m);
        if(vis[i]==0)
        {
            printf("No\n");
            continue;
        }
        int ans=0;
        for(int j=1;j<=n;j++)
        if(j!=i&&j!=m)
        {
            int ok=0;
            memset(vis,0,sizeof(vis));
            bfs(j,i);
            if(vis[i]==0)
            {
            ans++;
            printf("%d ",j);
            }
        } 
        if(ans==0) printf("No");
        printf("\n");
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值