题意:
有一个仓库,有很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; }
时间: 2024-09-28 21:56:51