您的位置:首页 > 其它

zoj 3811 Untrusted Patrol (按照顺序访问点+并查集||宽搜)

2014-09-11 10:57 330 查看
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3811

题意:

有n个点,其中有k个点是有摄像头的,然后会给出L个有序的点,要求按照顺序访问(后面没有被访问过的有摄像头的点,不能走)。

并查集:

首先遍历整张图,要将所有的无关点(没有摄像头的点),相同的合并到一个集合里面,然后在将有关点一个一个的合并进去,要是有不在一个集合的,那么就是走不通的

用vector的版本(最开始vector一直没有清空,导致wrong了很多次)

#include<stdio.h>
#include<string.h>
#include<vector>

#define mt(a,b) memset(a,b,sizeof(a))
#define MAX 100009
using namespace std;
int point[MAX],seq[MAX];
bool mark[MAX];
vector <int> vec[MAX];
struct Node {
int s;
int e;
} edge[MAX*2];
struct Ele {
int parent;
int num;
} elem[MAX];
void make_set(int n) {
for(int i=1; i<=n; i++) {
elem[i].parent=i;
elem[i].num=1;
}
}
int Find(int x) {
int root,temp;
temp=x;
while(x!=elem[x].parent)    //寻找根节点
x=elem[x].parent;
root=x;
x=temp;
while (x!=elem[x].parent) {//压缩路径,全部赋值为根节点的值
temp=elem[x].parent;
elem[x].parent=root;
x=temp;
}
return root;
}
void Union(int a,int b) { //合并两个集合
int x,y;
x=Find(a);
y=Find(b);
if(elem[x].num>=elem[y].num) {
elem[y].parent=elem[x].parent;
elem[x].num+=elem[y].num;
} else {
elem[x].parent=elem[y].parent;
elem[y].num+=elem[x].num;
}
}
int main() {
int T,n,m,k,L;
scanf("%d",&T);
while(T--) {
memset(mark,false,sizeof(mark));
scanf("%d %d %d",&n,&m,&k);
for(int i=0; i<k; i++) {
scanf("%d",&point[i]);
mark[point[i]]=true;
}
for(int i=0;i<=n;i++) vec[i].clear();
for(int i=0; i<m; i++) {
scanf("%d %d",&edge[i].s,&edge[i].e);
vec[edge[i].s].push_back(edge[i].e);
vec[edge[i].e].push_back(edge[i].s);
}
scanf("%d",&L);
for(int i=0; i<L; i++) {
scanf("%d",&seq[i]);
}
if(L!=k) {
printf("No\n");
continue;
}
make_set(n);
int len;
bool flag=false;
mark[seq[0]]=false;
for(int i=1;i<=n;i++){
if(mark[i]==false){
len=vec[i].size();
for(int j=0;j<len;j++){
if(mark[vec[i][j]]==false){
Union(i,vec[i][j]);
}
}
}
}
len=vec[seq[0]].size();
for(int i=0; i<len; i++) {
if(mark[vec[seq[0]][i]]==false)
Union(seq[0],vec[seq[0]][i]);
}
for(int i=1; i<L; i++) {
mark[seq[i]]=false;
len=vec[seq[i]].size();
for(int j=0; j<len; j++) {
if(mark[vec[seq[i]][j]]==false) {
Union(seq[i],vec[seq[i]][j]);
}
}
int fa = Find(seq[i-1]);
int fb = Find(seq[i]);
if(fa!=fb) {
flag=true;
break;
}
}
bool flag1=false;
int fa=Find(1);
for(int i=2; i<=n; i++) {
int fb=Find(i);
if(fa!=fb) {
flag1=true;
break;
}
}
if(flag==false&&flag1==false) printf("Yes\n");
else printf("No\n");
}
return 0;
}


宽搜:

按照顺序,从每个有摄像头的地方顺次的搜索,直到不能扩展为止,那么当第seq[i]这个点扩展完整为止,要是seq[i+1]这个没有被扩展到,那么一定不能完成任务了。

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#define MAX 100009
using namespace std;
vector <int> vec[MAX];
bool mark[MAX];//用于标记是否有路灯
bool used[MAX];//标记找一对顶点的过程中的点,是否被访问过
struct Node{
int s;
int e;
}edge[2*MAX];
int point[MAX],seq[MAX];
void deal(int f) {
queue<int>Que;
while(!Que.empty()) Que.pop();
Que.push(f);
used[f]=true;
mark[f]=false;
while(!Que.empty()) {
int tmp=Que.front();
Que.pop();
//printf("~~%d\n",tmp);
if(mark[tmp]==false) {
int len=vec[tmp].size();
for(int i=0; i<len; i++) {
if(used[vec[tmp][i]]==false) {
Que.push(vec[tmp][i]);
used[vec[tmp][i]]=true;
}
}
}
}
}
int main() {
int T,n,m,k,L;
scanf("%d",&T);
while(T--) {
scanf("%d %d %d",&n,&m,&k);
memset(mark,false,sizeof(mark));
for(int i=0;i<=n;i++) vec[i].clear();
for(int i=0; i<k; i++) {
scanf("%d",&point[i]);
mark[point[i]]=true;
}
for(int i=0; i<m; i++) {
scanf("%d %d",&edge[i].s,&edge[i].e);
vec[edge[i].s].push_back(edge[i].e);
vec[edge[i].e].push_back(edge[i].s);
}
scanf("%d",&L);
for(int i=0; i<L; i++) {
scanf("%d",&seq[i]);
}
if(L!=k) {
printf("No\n");
continue;
}
int i;
memset(used,false,sizeof(used));
deal(seq[0]);
for(i=1; i<L; i++) {
if(used[seq[i]]==false) break;
deal(seq[i]);
}
bool num=false;
for(int j=1;j<=n;j++){
if(used[j]==false) {
num=true;
break;
}
}
if(i==L&&num==false) printf("Yes\n");
else printf("No\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: