您的位置:首页 > 其它

ZOJ 3811 dfs&并查集

2016-05-28 14:32 295 查看
点击打开链接

题意:给n个城镇,有的城镇会发光,给出发光的城镇,然后下面有一个人走的发光的城镇的顺序,每个城镇只会发一次光,问这个人按这个顺序是否合法并且所有的城镇都被访问到

思路:可以用dfs去搜索,第一个点进去,不能走的点标记一下,然后第二个发光的城镇,判断目前标记的点中有没有,有的话说明现在可以走第二个点,以此类推,最后判断城镇是否全被访问过,一会试试并查集的方法

#include <queue>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=100010;
int vis1[maxn],vis2[maxn],id[maxn],vis[maxn],ansvis[maxn];
vector<int>G[maxn];
void dfs(int u){
if(vis[u]) return ;
vis[u]=1;
for(unsigned int i=0;i<G[u].size();i++){
int t=G[u][i];
if(vis[t]) continue;
if(vis2[t]) ansvis[t]=1;
else dfs(t);
}
}
int main(){
int T,n,m,k,u,v,l;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<maxn;i++) G[i].clear();
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
memset(vis,0,sizeof(vis));
memset(ansvis,0,sizeof(ansvis));
for(int i=0;i<k;i++){
scanf("%d",&u);vis1[u]=1;
}
for(int i=0;i<m;i++) {
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
scanf("%d",&l);
for(int i=0;i<l;i++){
scanf("%d",&id[i]);vis2[id[i]]=1;
}
int sum=0;
for(int i=0;i<k;i++) if(vis1[id[i]]&&vis2[id[i]]) sum++;
if(sum!=k||l!=k){
printf("No\n");
continue;
}
vis2[id[0]]=0;dfs(id[0]);
int flag=0;
for(int i=1;i<l;i++){
if(ansvis[id[i]]){
vis2[id[i]]=0;
dfs(id[i]);
}else{
flag=1;break;
}
}
for(int i=1;i<=n;i++) if(vis[i]==0) flag=1;
if(flag) printf("No\n");
else printf("Yes\n");
}
return 0;
}
是想到并查集的方法了,太麻烦不想写了,而且我的想法还是要基于DFS的,所以不如就只有dfs了,太弱~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: