您的位置:首页 > 理论基础 > 计算机网络

2014牡丹江网络zoj3816Generalized Palindromic Number(dfs或者bfs)

2014-09-08 15:22 405 查看
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#include <sstream>
#define INF 1000000000
#define ll long long
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define MAXN 100010

using namespace std;

bool mk[100010];
bool vis[100010];
bool open[100010];

vector<int> E[100010];
queue<int> K;

int main(){
int t;
cin>>t;
while(t--){
memset(mk,0,sizeof(mk));
memset(E,0,sizeof(E));
memset(vis,0,sizeof(vis));
memset(open,0,sizeof(open));
while(!K.empty()) K.pop();

int n,m,k;
cin>>n>>m>>k;

for(int i=1;i<=k;i++){
int tmp;
cin>>tmp;
}

for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
E[u].push_back(v);
E[v].push_back(u);
}

int L;
cin>>L;

for(int i=1;i<=L;i++){
int tmp;
cin>>tmp;
mk[tmp]=1;
K.push(tmp);
}
if(L<k){
cout<<"No"<<endl;
continue;
}

bool ok=0;

int nt;
int start=K.front(); K.pop(); mk[start]=0; vis[start]=1;
queue<int> que;
que.push(start);
if(!K.empty())  nt=K.front();
while(!que.empty()){
int cur=que.front(); que.pop();
int siz=E[cur].size();
for(int i=0;i<siz;i++){
int v=E[cur][i];
if(!vis[v]&&!mk[v]){
vis[v]=1;
que.push(v);
}

if(v==nt&&!vis[v]){
vis[v]=1;
que.push(v);
mk[v]=0;
K.pop();
if(!K.empty()) nt=K.front();
}
else if(!vis[v]&&mk[v])
open[v]=1;
}

if(que.empty()){
if(open[nt]==1&&!vis[nt]){
K.pop();
que.push(nt);
mk[nt]=0;
vis[nt]=1;
if(!K.empty())
nt=K.front();
}
}
}

bool flag=true;
for(int i=1; i<=n; ++i)
if(!vis[i]){
flag=false;
break;
}
if(K.empty() && flag) ok=1;
if(ok){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}

}
return 0;

}


/*
题意: 给定一个n个节点m条边的无向图,接着又给出一个序列(由图中的一些节点所组成)
问能否按照给定序列的顺序来访问图,并且保证图可以访问完毕!

思路:是可以走回头路的搜索!那么我们就按照给定的序列进行搜索,如果当前的节点在给定序列中
出现过,但是访问的顺序和给定序列的顺序不一样,那么就将该节点标记一下open[];
第一次搜索完毕之后,接着从open[]标记的节点(并且该节点符合给定序列的顺序)开始搜索!
最后不要忘记检查图的连通性....
如果不清楚,还是看代码吧....
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#define N 100005
using namespace std;

vector<int>g
;
int vis
, open
;
int mk
, que
;
int n, m, k, l, cnt;
bool flag;

void init(){
memset(vis, 0, sizeof(vis));
memset(open, 0, sizeof(open));
memset(mk, 0, sizeof(mk));
memset(g, 0, sizeof(g));
}

void dfs(int u){
vis[u]=1;
open[u]=0;
if(u==que[cnt]){
++cnt;
if(cnt>k) flag=true;
}
else if(mk[u])
vis[u]=0;
int len=g[u].size();
for(int i=0; i<len; ++i){
int v=g[u][i];
if(!vis[v]){
if(mk[v] && v!=que[cnt]){
open[v]=1;
continue;
}
if(open[v] && v!=que[cnt])
continue;
dfs(v);
}
}
}

int main(){
int t;
scanf("%d", &t);
while(t--){
init();
scanf("%d%d%d", &n, &m, &k);
for(int i=1; i<=k; ++i){
int x;
scanf("%d", &x);
mk[x]=1;
}

while(m--){
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
scanf("%d", &l);
for(int i=1; i<=l; ++i)
scanf("%d", &que[i]);
if(l<k){
printf("No\n");
continue;
}
cnt=1;
flag=false;
open[que[cnt]]=1;
while(cnt<=k){//就是从给定序列节点开始并且open标记开始搜索
if(!open[que[cnt]]) break;//如果访问到给定序列的当前节点没有被open标记,说明
dfs(que[cnt]);            //不能按照给定的序列的顺序访问图中的节点
}
if(flag){
int i;
for(i=1; i<=n; ++i)
if(!vis[i])  break;
if(i>n)
printf("Yes\n");
else printf("No\n");
}
else
printf("No\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: