这道题正着做有点难办,我们考虑倒序处理。
先把所有的边连在一起,再一条一条删边。
每次把入度小于k的点都删掉就行了。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #define bro(i) ((i%2)?(i+1):(i-1)) 6 using namespace std; 7 8 int n,m,k; 9 int hd[200005],to[400005],nx[400005],ec; 10 int cp[200005][2]; 11 bool de[400005]; 12 int deg[200005]; 13 int ans[200005]; 14 int tot; 15 bool del[200005]; 16 17 void edge(int af,int at) 18 { 19 to[++ec]=at; 20 nx[ec]=hd[af]; 21 hd[af]=ec; 22 deg[at]++; 23 } 24 25 queue<int>qq; 26 27 void split() 28 { 29 while(!qq.empty()) 30 { 31 int p=qq.front(); 32 qq.pop(); 33 if(del[p])continue; 34 del[p]=1; 35 tot--; 36 for(int e=hd[p];e;e=nx[e]) 37 { 38 if(de[e])continue; 39 int t=to[e]; 40 deg[t]--; 41 if(deg[t]<k&&(!del[t])) 42 { 43 qq.push(t); 44 } 45 } 46 } 47 } 48 49 int main() 50 { 51 scanf("%d%d%d",&n,&m,&k); 52 for(int i=1;i<=m;i++) 53 { 54 scanf("%d%d",&cp[i][0],&cp[i][1]); 55 edge(cp[i][0],cp[i][1]); 56 edge(cp[i][1],cp[i][0]); 57 } 58 tot=n; 59 for(int i=1;i<=n;i++) 60 if(deg[i]<k)qq.push(i),split(); 61 for(int i=m;i;i--) 62 { 63 ans[i]=tot; 64 hd[cp[i][0]]=nx[hd[cp[i][0]]]; 65 hd[cp[i][1]]=nx[hd[cp[i][1]]]; 66 for(int j=1;j>=0;j--) 67 if(!del[cp[i][j]]) 68 deg[cp[i][1-j]]--; 69 for(int j=1;j>=0;j--) 70 if(deg[cp[i][j]]<k) 71 qq.push(cp[i][j]),split(); 72 } 73 for(int i=1;i<=m;i++)printf("%d ",ans[i]); 74 return 0; 75 }