题目:戳这里
题意:n个点,每天早上会在这n个点中加一条边,每天晚上最大的子图满足子图中每个点都有k条或以上的边。
解题思路:看了官方题解,先把所有的点都连上,再从最后一天往前减边,用set维护最大的子图,注意每减去一条边时,更新该边两端点的状态。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 2e5 + 10; 5 int ans[maxn]; 6 struct edge 7 { 8 int u; 9 int v; 10 }eg[maxn]; 11 int cnt[maxn]; 12 int n, m, k; 13 set<int>st; 14 set<int>nu[maxn]; 15 void del(int x)//更新点的状态 16 { 17 if(nu[x].size() < k && st.erase(x)) 18 { 19 for(auto &i:nu[x]) 20 { 21 // printf("%d %d ", x, i); 22 nu[i].erase(x); 23 del(i); 24 } 25 } 26 } 27 int main() 28 { 29 scanf("%d %d %d", &n, &m, &k); 30 for(int i = 1; i <= m; ++i) 31 { 32 scanf("%d %d", &eg[i].u, &eg[i].v); 33 nu[eg[i].u].insert(eg[i].v); 34 nu[eg[i].v].insert(eg[i].u); 35 } 36 // for(auto &i: nu[4]) 37 // { 38 // printf("%d ", i); 39 // } 40 for(int i = 1; i <= n; ++i) 41 { 42 st.insert(i); 43 } 44 for(int i = 1; i <= n; ++i)//更新出最后一天的最大子图 45 { 46 del(i); 47 } 48 for(int i = m; i >= 1; -- i)//更新之前的 49 { 50 ans[i] = st.size(); 51 if(st.empty()) break; 52 nu[eg[i].u].erase(eg[i].v); 53 nu[eg[i].v].erase(eg[i].u); 54 del(eg[i].u); 55 del(eg[i].v); 56 } 57 for(int i = 1; i <= m; ++i) 58 { 59 printf("%d ",ans[i]); 60 } 61 }