题意:在某些点上安装首次访问时候会报警的机器,给出报警嗲你的顺序,问是否合法。
思路:按所给的序列,每个进来时判断这个点目前能否达到(第一个可达总是),若能,则该点进行扩展遍历所有没有报警器的点,遇到有的报警器的标记可达就返回。
预判:判断原图连图性。
#include<iostream> #include<queue> #include<cstdio> #include<vector> #include<cstring> using namespace std; vector<vector<int> >g(100010); int has[100010]; vector<int>jud; int n,m,k,l; int vis[100010]; bool bfs() { memset(vis,0,sizeof(vis)); queue<int>q; q.push(1); vis[1]=1; while(!q.empty()) { int cur=q.front(); q.pop(); for(int i=0;i<g[cur].size();i++) { int v=g[cur][i]; if(vis[v]==0) { vis[v]=1; q.push(v); } } } for(int i=1;i<=n;i++) { if(vis[i]==0) { return 0; } } return 1; } void dfs(int u) { if(has[u]==1&&vis[u]==0) { vis[u]=1; return ; } for(int i=0;i<g[u].size();i++) { int v=g[u][i]; if(vis[v]==0&&has[v]==0) { vis[v]=1; dfs(v); } else if(vis[v]==0) { dfs(v); } } return ; } void init() { for(int i=0;i<=n;i++) { has[i]=0; g[i].clear(); vis[i]=0; } jud.clear(); } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&k); init(); int tx,ty; for(int i=0;i<k;i++) { scanf("%d",&tx); has[tx]=1; } for(int i=0;i<m;i++) { scanf("%d%d",&tx,&ty); g[tx].push_back(ty); g[ty].push_back(tx); } scanf("%d",&l); for(int i=0;i<l;i++) { scanf("%d",&tx); jud.push_back(tx); } if(l!=k||bfs()==0) { printf("No\n");continue; } memset(vis,0,sizeof(vis)); bool marks=1; vis[jud[0]]=1; for(int i=0;i<l;i++) { if(vis[jud[i]]==0) { marks=0;break; } dfs(jud[i]); } if(marks) printf("Yes\n"); else printf("No\n"); } return 0; }
时间: 2024-10-12 19:54:59