ZOJ-1085-Alien Security

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1085

题目大意:

研究机构的每个房间由单向密封过渡仓连接,所以进去只能一个方向通过。

设置守卫室的位置,使其满足一下条件:

1、  要到达et位置,客人必须通过守卫室的房间

2、  没有其他房间更接近放有et的房间,守卫室不能设在et所在的位置

所有客人必须首先进入0号房间,这是入口

程序输入有多行,第一行有两个整数:房间的数目,et所在的位置

其余各行也有两个整数,指明通向,第一个源房间,第二个目标房间,单向。

程序输出只有一行 Put guards in room N.              N是守卫室的位置

题目包含多组数据,第一行是N,表示N组测试数据,每组数据格式与问题描述一样,组数据间有一个空行

算法分析:

       刚开始看这道题的时候对题目理解有误,写了程序提交后错了几次,后来看书,才发现题意没有理解清楚,题目要求要到达et,必须经过守卫室,并且次位置最接近et位置实际是要求,守卫室是必要通道,去掉这个位置,就不可能到达et,并且求最近的这样一个点

       这道题要用到广度搜索和深度搜索,广度搜索求得各个点到et的最近距离,次题是方向是单向的,从et的位置看,反向看方向即可。

       然后一次搜索每个房间i,从0入口,求不经过i就不能到达et的位置,并比较求得一个最接近et的位置

#include<iostream>

#include<cstring>

#include<cstdio>

#include<queue>

using namespace std;



#define MAXN 102

#define inf 1000000



int n,et;

int data[MAXN][MAXN];    //存储邻接矩阵

int dist[MAXN],used[MAXN];    //



int dfs(int id)

{

    if(id == et)        //如果能够到达et,返回1

        return 1;

    used[id] = 1;

    int i;

    for(i=0;i<n;i++)

    {

        if(!used[i] && data[id][i])    //搜索房间id的相邻边

        {

            if(dfs(i))    return 1;

        }

    }

    return 0;

}



void bfs()    //广度搜索,求得各个顶点到et的最近距离

{

    int x,y;

    for(x=0;x<n;x++)

        dist[x] = inf;

    dist[et] = 0;

    queue<int> Q;

    Q.push(et);

    while(!Q.empty())

    {

        y = Q.front();    Q.pop();

        for(x=0;x<n;x++)

        {

            if(data[x][y] && dist[y] + 1 < dist[x])

            {

                Q.push(x);

                dist[x] = dist[y] + 1;

            }

        }

    }

}



int main()

{

    int T,iCase,i,x,y,d,ans;

    char str[10];

    scanf("%d",&T);

    for(iCase=0;iCase<T;iCase++)

    {

        scanf("%d%d\n",&n,&et);

        memset(data,0,sizeof(data));

        while(gets(str))

        {            

            if(strcmp(str,"") == 0)    break;

            sscanf(str,"%d%d",&x,&y);

            data[x][y] = 1;    //有向

        }

        bfs();

        d = dist[0];

        ans = 0;

        for(i=1;i<n;i++)    //

        {

            if(i == et) continue;

            memset(used,0,sizeof(used));

            used[i] = 1;

            if(!dfs(0) && dist[i] < d)    //如果不经过i点,则不能到达et,满足

            {

                ans = i;

                d = dist[i];    //更新最短距离

            }

        }

        if(iCase)    printf("\n");

        printf("Put guards in room %d.\n",ans);

    }

    return 0;

}

 

你可能感兴趣的:(Security)