题解:Trips
传送门:http://codeforces.com/contest/1037/problem/E
分析:
1)正向建图搞鼓半天不会做。
2)那离线?反向建图?
3)删掉去不了的人,同时删掉相连的边。
4)就是一个奇特的类似拓扑的过程。
5)可以利用$std::set$存边删边。
#include <bits/stdc++.h> using namespace std; const int maxN=2e5+5; queue<int>q; set<int>G[maxN]; int n,m,k; int tans,ans[maxN],u[maxN],v[maxN],vis[maxN]; void Deal(){ for(;!q.empty();){ int v=q.front();q.pop();--tans; for(auto i:G[v]){ G[i].erase(v); if((int)G[i].size()<k && !vis[i]){q.push(i);vis[i]=1;} } G[v].clear(); } } int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;++i){ scanf("%d%d",u+i,v+i); G[u[i]].insert(v[i]); G[v[i]].insert(u[i]); } tans=n; for(int i=1;i<=n;++i)if((int)G[i].size()<k){q.push(i);vis[i]=1;} for(int i=m;i;--i){ Deal();ans[i]=tans; if(!G[u[i]].count(v[i]))continue; G[u[i]].erase(v[i]);G[v[i]].erase(u[i]); if((int)G[u[i]].size()<k && !vis[u[i]]){q.push(u[i]);vis[u[i]]=1;} if((int)G[v[i]].size()<k && !vis[v[i]]){q.push(v[i]);vis[v[i]]=1;} } for(int i=1;i<=m;++i)printf("%d ",ans[i]); return 0; }