P1197 [JSOI2008] Star Wars (reverse thinking, disjoint-set)

Meaning of the questions:

Give you an undirected graph, each point omitted from the drawing, the number of interrogation points after each puncturing block in FIG communication

Ideas:

This problem can be off-line, off-line so we reverse the practice

How a reverse it? We assume that after only a starting point for all operations delete points, and calculates the number of connected blocks

After each addition points deleted in the drawing, communication, and count the number of blocks

If the re-run again, then all points on the time complexity will be fried, for the newly added point, we first add the number of the current communication block 1, if all the points of the traverse point of attachment, if able to merge, then the communication will be Save a number of blocks

Finally, the answer is like a reverse output

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
 using namespace std;
 const int maxn=4e5+1000;
 int flag[maxn],fa[maxn];
 vector<int>a[maxn];
 stack<int> s,q;
 int find(int x){return fa[x]==x?x:(fa[x]=find(fa[x]));}
 int main()
 {
     int n,m,k,u,v;
     memset(flag,1,sizeof(flag));
     scanf("%d%d",&n,&m);
     for(int i=1;i<=m;i++){
         scanf("%d%d",&u,&v);
         a[u].push_back(v);
         a[v].push_back(u);
     }
    scanf("%d",&k);
    for(int i=1;i<=k;i++){
        scanf("%d",&u);
        s.push(u);
        flag[u]=0;
    }
    int cnt=n-k; 
    for(int i=0;i<n;i++) fa[i]=i;
    for(int i=0;i<n;i++){
        if(!flag[i])    continue;
        else{
            for(int j=0;j<a[i].size();j++){
                if(flag[a[i][j]]){
                    int f1=find(a[i][j]),f2=find(i);
                    if(f1!=f2)    fa[f1]=find(fa[f2]),cnt--;
                }
            }
        }
    }
    q.push(cnt);
    for(int i=1;i<=k;i++){
        cnt++;
        int x=s.top();
        s.pop();
        for(int j=0;j<a[x].size();j++){
            if(flag[a[x][j]]){
                int f1=find(a[x][j]),f2=find(x);
                if(f1!=f2)    fa[f1]=find(fa[f2]),cnt--;
            }
        }
        flag[x]=1;
        q.push(cnt);
    }
    while(!q.empty()){
        cout<<q.top()<<endl;
        q.pop();
    }
    return 0;
 }

 

Guess you like

Origin www.cnblogs.com/overrate-wsj/p/12291462.html