您的位置:首页 > 编程语言 > C语言/C++

【7.13考试第二题】RQNOJ190 拦截匪徒

2016-07-15 14:00 295 查看
【问题描述】

某城市的地图是一个由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的顺序输出,若有多点,由小到大顺序输出。如果没有合适的埋伏位置,或者在p与j根本就不连通,则输出No。

【输入输出样例1】

输入

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是否连通。

故枚举终点j和警察埋伏点k,然后判断删去k后p和j是否仍然连通,如果不连通则说明这个点可行,压入变长数组中,根据变长数组中元素个数输出。

当然每一个枚举的终点j应和p连通(用并查集或BFS判断)

一点“辛酸”的总结:

最后做的这个题,这个题其实算不上难题,但是比较坑,一开始读题的时候找不到什么思路,直接跳过了,后来开始做的时候已经是4点了,还有一个小时,感觉比较急,直接就开始做了,觉得是枚举删去埋伏的那个点然后二分图判定,完美打偏了,后来想到直接判定连通性,已经4点半了,又觉得BFS要TLE,然后用并查集假删除。做得很复杂,调的时候也总是不对。下次做题还是不能太急,不管有多少时间都要慢慢来,还有就是高级方法不好做不如想想其他看似低级的方法。



(看到这题解的枚举范围,我的内心毫无波澜)

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxn 305
using namespace std;
int n,p,rear,front;
int pa[2*maxn],id[2*maxn],vis[2*maxn],q[2*maxn];
vector<int>ep;
vector<int>g[maxn];
void initial()
{
for(int i=1;i<=n;i++)pa[i]=i,id[i]=i;
}

int find(int x)
{
return pa[x] = pa[x]==x? x:find(pa[x]);
}

void Union(int x,int y)
{
pa[find(x)]=find(y);
}

bool judge(int x,int y)
{
return find(x)==find(y);
}

void BFS(int s)
{
rear=front=1;
q[rear++]=s;
vis[s]=1;
while(rear!=front)
{
int i=q[front++];
for(int k=0;k<g[i].size();k++)
{
int j=g[i][k];
if(vis[j])continue;
vis[j]=1;
q[rear++]=j;
}
}
}

int main()
{
//freopen("my.in","r",stdin);
//freopen("my.out","w",stdout);

scanf("%d%d",&n,&p);

initial();
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);
Union(i,j);
}
}

for(int i=1;i<=n;i++)if(i!=p)
{
ep.clear();
for(int k=1;k<=n;k++)if(k!=p && k!=i)//假设删除k
{
memset(vis,0,sizeof(vis));
vis[k]=1;
BFS(p);
if(!vis[i])
ep.push_back(k);
}
if(ep.size()>0 && judge(p,i))
{
for(int k=0;k<ep.size();k++)
printf("%d ",ep[k]);
printf("\n");
}
else printf("No\n");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ 算法竞赛