简述题意:
给一幅图,边从 0 开始每天多一条边,问每天增加边之后能够有多少人去旅游。能去旅游的定义是只有当联通的点的度数都大于等于 k 才能去旅游,否则都不能去旅游。
Examples
Input
4 4 2
2 3
1 2
1 3
1 4
Output
0
0
3
3
Input
5 8 2
2 1
4 2
5 4
5 2
4 3
5 1
4 1
3 2
Output
0
0
0
3
3
4
4
5
Input
5 7 2
1 5
3 2
2 5
3 4
1 2
5 3
1 3
Output
0
0
0
0
3
4
4
这一题正向考虑不好做,反过来想,若果是从最后一天开始,不断删除边,就会简单很多
首先假设所有人都会去,然后去掉入度小于k的点,并删去相关的边,然后再找到入度小于k的点,删去相关边......
用一个类似拓扑排序的过程解决
#include<bits/stdc++.h> using namespace std; const int N=2*(1e5+5); int n,m,k; vector<int> to[N]; struct edge { int a,b; bool del; }e[N]; bool vis[N]; int deg[N],ans,f[N]; int main() { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;++i) { scanf("%d%d",&e[i].a,&e[i].b); ++deg[e[i].a],++deg[e[i].b]; to[e[i].a].push_back(i); to[e[i].b].push_back(i); e[i].del=0; } ans=n; queue<int> q; for(int i=1;i<=n;++i) if(deg[i]<k) {q.push(i);--ans,vis[i]=1;} while(!q.empty()) { int u=q.front();q.pop(); for(int i=0;i<to[u].size();++i) { int y=to[u][i],v=(e[y].a==u)?e[y].b:e[y].a; if(e[y].del) continue; --deg[v],--deg[u],e[y].del=1; if(deg[v]<k && !vis[v]) {q.push(v);--ans,vis[v]=1;} } } for(int i=m;i>=1;--i) { f[i]=ans; if(e[i].del) continue; e[i].del=1,--deg[e[i].a],--deg[e[i].b]; if(deg[e[i].a]<k && !vis[e[i].a]) {q.push(e[i].a);--ans,vis[e[i].a]=1;} if(deg[e[i].b]<k && !vis[e[i].b]) {q.push(e[i].b);--ans,vis[e[i].b]=1;} while(!q.empty()) { int u=q.front();q.pop(); for(int j=0;j<to[u].size();++j) { int y=to[u][j],v=(e[y].a==u)?e[y].b:e[y].a; if(e[y].del) continue; --deg[v],--deg[u],e[y].del=1; if(deg[v]<k && !vis[v]) {q.push(v);--ans,vis[v]=1;} } } } for(int i=1;i<=m;++i) printf("%d\n",f[i]); return 0; }