Cpp环境【NOIP2012模拟题】【Vijos3013】拦截匪徒

【问题描述】  

  某城市的地图是一个由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
【思路梳理】
没有太多技术含量,对于歹徒的逃跑路线p->j如果警察埋伏在k点使得能够将匪徒抓获,那么就是说删除掉节点k后p与j不再连通。因为数据不大,所以可对于每一个节点都进行穷举,判断删除某个节点k后p与j是否连通,如果不能连通,那么k就是一个可以抓获歹徒的点。
【Cpp代码】

#include
#include
#include
#include
#include
#define maxn 305
using namespace std;
int n,p;
vector<int>g[maxn];
bool vis[maxn],d[maxn];

void DFS(int i)
{
    d[i]=true;
    for(int j=0;jint k=g[i][j];
        if(d[k])    continue;
        DFS(k);
    }
}

bool BFS(int e,int ignore)
{
    memset(vis,0,sizeof(vis));
    queue<int>q;
    q.push(p);
    vis[p]=true;

    while(!q.empty())
    {
        int i=q.front();q.pop();
        if(i==e)    return true;
        for(int j=0;jint k=g[i][j];
            if(k==ignore || vis[k]) continue;
            q.push(k);
            vis[k]=true;
        }
    }
    return false;
}
int main()
{
    //freopen("in.txt","r",stdin);
    cin>>n>>p;

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

    for(int i=1;i<=n;i++)if(i!=p)
    {
        bool ok=false;
        if(d[i])
        {
            for(int j=1;j<=n;j++)
            {
                if(j==p || j==i)    continue;
                if(!BFS(i,j))
                {
                    ok=true;
                    printf("%d ",j);
                }
            }
        }
        if(!ok) printf("No");   
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(数据结构之三,图型结构,基础算法之二,暴力枚举,难度评级,Casual)