codeforces 1037E Trips

       题目大意:有n一开始互不认识的人聚到了一起,每天晚上,都会有两个互不认识的人相互认识。从聚会开始那一天算起,连续m天都有旅行计划。一个人参加旅行的条件是有至少k个他认识的人也参加了旅行。求每天最多有几个人参加旅行。

       输入:第一行三个整数,分别是n(2<=n<=200000),m(1<=m<=200000)和k(1<=k<n)。接下来m行,每行两个数字,表示当天晚上这两个人互相认识了(每天先相互认识再开始旅行)。

       输出:一共m行,每行一个数字,表示当天最多有多少人参加旅行。

       题解:

       逆向思维的图论题目。

       模型可以抽象为求度数大于等于k的点组成的图最多有几个点,从加边考虑会变得相当复杂,因此考虑先加入所有边,之后问题变成删去若干条边。考虑到度数小于k的点不可能成为答案,于是可以将其删去,重复直到整张图中只剩下度数大于等于k的点,这时候点数就是答案。在加边的时候记录下每次加的是哪一条,反过来一条条删去即可。

       (其实之前写过类似思路的题目……所以写不出来的我是真的菜)

       代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 200010
using namespace std;

int n,m,k,num=1,sum,L,R;
int fst[maxn],lst[maxn<<1],to[maxn<<1];
int du[maxn],q[maxn],ans[maxn],Q[maxn];
bool f[maxn],ex[maxn<<1];

inline void insert(int u,int v)
{
	lst[++num]=fst[u];to[num]=v;fst[u]=num;ex[num]=1;
	lst[++num]=fst[v];to[num]=u;fst[v]=num;ex[num]=1;
}

void del(int x)
{
	int a=to[x],b=to[x^1];
	ex[x]=0;ex[x^1]=0;du[a]--;du[b]--;
	if(du[a]==k-1&&f[a]) Q[R++]=a;if(du[b]==k-1&&f[b]) Q[R++]=b;
	while(L!=R)
	{
	  a=Q[L++];f[a]=0;sum--;
	  for(int i=fst[a];i;i=lst[i]) if(ex[i]){ex[i]=0;ex[i^1]=0;du[to[i]]--;if(du[to[i]]==k-1&&f[to[i]]) Q[R++]=to[i];}
	}
}

int main()
{
	int a,b;
	scanf("%d%d%d",&n,&m,&k);sum=n;
	for(int i=1;i<=m;i++){scanf("%d%d",&a,&b);insert(a,b);q[i]=num;du[a]++;du[b]++;}
	L=1;R=1;
	for(int i=1;i<=n;f[i]=1,i++) if(du[i]<k) Q[R++]=i;
	while(L!=R)
	{
	  a=Q[L++];f[a]=0;sum--;
	  for(int i=fst[a];i;i=lst[i]) if(ex[i]){ex[i]=0;ex[i^1]=0;du[to[i]]--;if(du[to[i]]==k-1&&f[to[i]]) Q[R++]=to[i];}
	}
	for(int i=m;i;i--){ans[i]=sum;if(ex[q[i]]) del(q[i]);}
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值