看了题解又调了很久,用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]<<' '; }