题目大意:给一个无向图,有些点有装监视器记录第一次到达该点的位置,问是否存在一条路径使得监视器以给定的顺序响起,并且经过所有点
思路:牡丹江网络赛的题,当时想了种并查集的做法,通神写完程序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 ");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 ");
else printf("Yes ");
}
return 0;
}