NKOJ P3696 假期关楼 (并查集)

时间限制 : - MS   空间限制 : 65536 KB
评测说明 : 因文件输入输出过大,时限2000ms
问题描述

暑假到了,大部分学生都回家了,只有少量竞赛学生还在学校里。
学校打算逐步把教学楼都关闭。以减少运营成本。
学校里的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\n"); 
        else
        printf("NO\n"); 
    }
    
    
    
    
}

猜你喜欢

转载自www.cnblogs.com/OIEREDSION/p/11260285.html
今日推荐