连通图,set——cf1037E

 看了题解又调了很久,用set来维护当前满足条件的pair<degree[v],v>

离线操作,先建好一张图,然后建立好集合,每次删边后都把集合里不满足条件的点删去,同时更新集合

/*
离线操作 
*/
#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define maxn 200005
vector<int>G[maxn];
int n,m,degree[maxn],k;
set<pair<int,int> >s;
set<pair<int,int> >::iterator it;
struct E{int x,y;}e[maxn];
int ans[maxn];

int main(){
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        cin>>e[i].x>>e[i].y;
        ++degree[e[i].x],++degree[e[i].y];
        G[e[i].x].push_back(e[i].y);
        G[e[i].y].push_back(e[i].x);
    }
    for(int i=1;i<=n;i++)s.insert(make_pair(degree[i],i));
    for(int i=m;i>=1;i--){
        while(s.size()){
            pair<int,int>p=*(s.begin());
            int  u=p.second;
            
            if(degree[u]<k){
                for(int i=0;i<G[u].size();i++){
                    int v=G[u][i];
                    if(s.find(make_pair(degree[v],v))!=s.end()){
                        s.erase(make_pair(degree[v],v));
                        degree[v]--;
                        s.insert(make_pair(degree[v],v));
                    }
                }
                s.erase(make_pair(degree[u],u));
            }
            else break;
        }
        ans[i]=s.size();
        
      //当且仅当这条边的两个端点都在集合里,反之这条边贡献的degree肯定被删去过了
if(s.find(make_pair(degree[e[i].x],e[i].x))!=s.end() && s.find(make_pair(degree[e[i].y],e[i].y))!=s.end()){ s.erase(make_pair(degree[e[i].x],e[i].x)); degree[e[i].x]--; s.insert(make_pair(degree[e[i].x],e[i].x)); s.erase(make_pair(degree[e[i].y],e[i].y)); degree[e[i].y]--; s.insert(make_pair(degree[e[i].y],e[i].y)); } G[e[i].x].pop_back();G[e[i].y].pop_back();//删边 } for(int i=1;i<=m;i++)cout<<ans[i]<<' '; }
原文地址:https://www.cnblogs.com/zsben991126/p/10799491.html