题目链接
题意
每天早上有两人成为朋友,朋友之间不会传递;每天晚上举行一次聚会,对每个人来说他如果参加聚会,则不少于 k k k个他的朋友必须参加聚会.问每天晚上能参加聚会的最多人数.
题解
倒过来考虑,每天早上让一对朋友关系破裂.
则如果一个人没有
k
k
k个朋友,我们可以直接把他从聚会名单里面删掉,因为对任何一个人都能找到某一天使这天之前他都不能参加聚会,这天之后都能参加,这种方法显然正确.
当删除一个人之后,我们搜他的所有朋友,如果此时有朋友的朋友的数量小于
k
k
k个,我们可以进行连锁删除.
最后正向输出聚会名单的人数就可以了.
谢谢大家.
我唯一的疑问就是
void del(int x) {
if (g[x].size()<*u) {
s.erase(x);
for (auto i:g[x])
g[i].erase(x),del(i);
}
}
和
void del(int x) {
if (g[x].size()<*u&&s.erase(x))
for (auto i:g[x])
g[i].erase(x),del(i);
}
上面的MLE了,下面的AC了,让我觉得很奇怪.
AC代码如下.
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
const int yuzu=1e6;
typedef int fuko[yuzu|10];
fuko u,v,zw;
set<int> s,g[yuzu|10];
void del(int x) {
if (g[x].size()<*u&&s.erase(x))
for (auto i:g[x])
g[i].erase(x),del(i);
}
int main() {
int n,m,i;
scanf("%d%d%d",&n,&m,u);
for (i=1;i<=m;++i) {
scanf("%d%d",u+i,v+i);
g[u[i]].insert(v[i]);
g[v[i]].insert(u[i]);
}
for (i=1;i<=n;++i) s.insert(i);
for (i=1;i<=n;++i) del(i);
for (i=m;i;--i) {
zw[i]=s.size();
g[u[i]].erase(v[i]);
g[v[i]].erase(u[i]);
del(u[i]),del(v[i]);
}
for (i=1;i<=m;++i) printf("%d\n",zw[i]);
}