|
问题描述
暑假到了,大部分学生都回家了,只有少量竞赛学生还在学校里。
学校打算逐步把教学楼都关闭。以减少运营成本。
学校里的N栋教学楼(编号1到N)通过M条双向道路连接起来。每关闭了一栋楼,与该楼相连的所有道路同时都会被关闭。
何老板想知道,学校每关闭一栋楼,剩下的处于开放状态的教学楼是否是连通的。连通就是指任何两个开放的楼都可以相互到达。
注意,有可能一开始所有楼都不连通。
输入格式
第一行,一个两个整数N和M
接下来M行,每行两个整数x和y,表示x、y两栋楼间有道路直接相连。
接下来N行,每行一个整数代表一栋楼的编号。整个N行数字表示依次关闭的教学楼的顺序。
输出格式
共N行,每行是"YES"或者"NO",若剩下的楼是连通的输出YES,否则输出NO。
其中第1行表示一开始整个学校的楼是否连通。
其中第i+1行表示第i次关闭教学楼后,剩下的楼是否连通。
样例输入
4 3
1 2
2 3
3 4
3
4
1
2
样例输出
YES
NO
YES
YES
提示
对于40%的数据1≤N,M≤3000
对于100%的数据1≤N,M≤200000
为我当时智障用kruskal 判断 道路是否联通 而 自闭
按顺序关 判断集合 可以反向考虑 删边看作加边
每次联通块加1 判断当前新加的点 是否可以与已经在集合里面的点 合并 如果合并 ans++;
如果原联通块-ans==1 则可行
否则就不行
code:
// #include<bits/stdc++.h> using namespace std; int n,m; #define maxnn 600000 int f[maxnn]; int ans[maxnn],shun[maxnn]; int sec=0; int sta[maxnn],nex[maxnn],en[maxnn],tot,las[maxnn]; int mark[maxnn]; int gf(int v) { return f[v]==v? v:f[v]=gf(f[v]); } void add(int a,int b) { en[++tot]=b; nex[tot]=las[a]; las[a]=tot; sta[tot]=a; } int judge(int v) { int ans=0; mark[v]=1; for(int i=las[v];i;i=nex[i]) { int y=en[i]; if(mark[y]) { if(gf(y)!=gf(v)) { ans++; f[gf(y)]=gf(v); } } } return ans; } int main() { scanf("%d%d",&n,&m); int x,y; for(int i=1;i<=n;i++) { f[i]=i; } for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } for(int i=1;i<=n;i++) { scanf("%d",&shun[i]); } for(int i=n;i>=0;i--) { sec++; sec-=judge(shun[i]); if(sec==1) ans[i]=1; else ans[i]=0; } for(int i=1;i<=n;i++) { if(ans[i]==1) printf("YES "); else printf("NO "); } }