题目大意:给一个无向图,有些点有装监视器记录第一次到达该点的位置,问是否存在一条路径使得监视器以给定的顺序响起,并且经过所有点

思路:牡丹江网络赛的题,当时想了种并查集的做法,通神写完程序WA了几发,此时JYB用BFS秒了,索性最后还是调出来了,今天自己写了下,感觉唯一的坑点就是需要遍历完所有的点

//zoj3811

#include <stdio.h>

#include <string.h>

#include <algorithm>

#include <queue>

#define maxn 500000

#define inf 0x3f3f3f3f

using namespace std;

int father[maxn],head[maxn],point[maxn],next[maxn];

int n,m,k,a,b[maxn],now,x[maxn],y[maxn];

bool mark[maxn];

int find(int x)

{

if(father[x]==x)return x;

return father[x]=find(father[x]);

}

void add(int x,int y)

{

next[++now]=head[x];

head[x]=now;

point[now]=y;

}

int main()

{

int t,xx,yy,l;

scanf("%d",&t);

while(t--)

{

int flag=0,z=0;

now=0;

memset(head,0,sizeof(head));

memset(mark,0,sizeof(mark));

scanf("%d%d%d",&n,&m,&k);

for(int i=1;i<=n;i++)father[i]=i;

for(int i=1;i<=k;i++)

{

scanf("%d",&a);

mark[a]=1;

}

for(int i=1;i<=m;i++)

{

scanf("%d%d",&xx,&yy);

add(xx,yy);add(yy,xx);

x[i]=xx;y[i]=yy;

}

scanf("%d",&l);

for(int i=1;i<=l;i++)scanf("%d",&b[i]);

mark[b[1]]=0;

//if(l!=k){printf("No\n");continue;}

for(int i=1;i<=m;i++)

{

if(mark[x[i]]||mark[y[i]])continue;

xx=find(x[i]);yy=find(y[i]);

if(xx!=yy)

{

father[xx]=yy;

z++;

//   printf("%d  %d",x[i],y[i]);

}

}

for(int i=2;i<=l;i++)

{

mark[b[i]]=0;

for(int j=head[b[i]];j;j=next[j])

{

int u=point[j];

if(mark[u]==1)continue;

xx=find(b[i]);yy=find(u);

if(xx!=yy){father[xx]=yy;z++;}

}

xx=find(b[i]);yy=find(b[i-1]);

if(xx!=yy)

{

flag=1;break;

}

}

for(int i=1;i<=n;i++)if(find(i)!=find(b[1]))flag=1;

if(flag==1)printf("No\n");

else printf("Yes\n");

}

return 0;

}

05-20 13:00