题意:
有一个仓库,有很n个点,m条边,还有k个点有传感器;
现在给出n,m,k然后给出k个监视器的位置,给出m条边;
再输入l,表示总共有k个传感器被触发了(每个传感器只会第一次经过时触发);
和触发的顺序;
问可以可以把整张图走完 , 并且是按照给出的触发顺序;
思路:
我们一开始先把触发器所在的点排除,然后把其它点用并查集并起来;
然后按顺序一个个把触发器的点放进去;
假如我们现在放入第三个触发器;然后他和第二个触发器,并在了一起,说明可以走到(此时其它触发器都还没放进去,那么自然不存在触发顺序的问题)
到最后只要每个触发器放进去后,都可以和前一个并在一起,并且图是联通的,那么就可以;
AC代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 100000 + 10;
vector <int> e[N];
int p[N];
int findp(int x){
return x == p[x] ? x : p[x] = findp(p[x]);
}
int Union(int x,int y){
x = findp(x),y = findp(y);
if(x == y)
return false;
p[x]=y;
return true;
}
int mm[N],a[N],b[N];
int main(){
int n,m,k,t;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&k);
for(int i = 0; i <= n; i++){
e[i].clear();
p[i] = i;
mm[i] = 0;
}
for(int i = 1; i <= k; i++){
scanf("%d",&b[i]);
mm[b[i]] = 1;
}
for(int i = 0; i < m;i++){
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
int l,flag=0;
scanf("%d",&l);
for(int i=1;i<=l;i++){
scanf("%d",&a[i]);
if(!mm[a[i]]){
flag=1;
}
}
if(l!=k||flag){
puts("No");
continue;
}
mm[a[1]] = 0;
for(int i = 1;i <= n; i++){
if(mm[i])
continue;
for(int j = 0; j < e[i].size(); j++){
int v = e[i][j];
if(mm[v])
continue;
Union(i,v);
}
}
flag = 0;
for(int i = 2;i <= k;i++){
mm[a[i]] = 0;
for(int j = 0;j < e[a[i]].size(); j++){
int v = e[a[i]][j];
if(mm[v])
continue;
Union(a[i],v);
}
if(findp(a[i])!=findp(a[i-1])){
flag = 1;
break;
}
}
if(flag)
puts("No");
else {
memset(mm,0,sizeof(mm));
for(int i=1;i<=n;i++){
mm[findp(i)]++;
}
flag = 0;
for(int i = 1; i <= n; i++){
if(mm[i]==n)flag=1;
}
if(!flag)
puts("No");
else
puts("Yes");
}
}
return 0;
}