Manthan, Codefest 18 (rated, Div. 1 + Div. 2) E. Trips(BFS+删边)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37025443/article/details/82349880

E. Trips

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

There are nn persons who initially don't know each other. On each morning, two of them, who were not friends before, become friends.

We want to plan a trip for every evening of mm days. On each trip, you have to select a group of people that will go on the trip. For every person, one of the following should hold:

  • Either this person does not go on the trip,
  • Or at least kk of his friends also go on the trip.

Note that the friendship is not transitive. That is, if aa and bb are friends and bb and cc are friends, it does not necessarily imply that aa and cc are friends.

For each day, find the maximum number of people that can go on the trip on that day.

Input

The first line contains three integers nn, mm, and kk (2≤n≤2⋅105,1≤m≤2⋅1052≤n≤2⋅105,1≤m≤2⋅105, 1≤k<n1≤k<n) — the number of people, the number of days and the number of friends each person on the trip should have in the group.

The ii-th (1≤i≤m1≤i≤m) of the next mm lines contains two integers xx and yy (1≤x,y≤n1≤x,y≤n, x≠yx≠y), meaning that persons xx and yy become friends on the morning of day ii. It is guaranteed that xx and yy were not friends before.

Output

Print exactly mm lines, where the ii-th of them (1≤i≤m1≤i≤m) contains the maximum number of people that can go on the trip on the evening of the day ii.

Examples

input

Copy

4 4 2
2 3
1 2
1 3
1 4

output

Copy

0
0
3
3

input

Copy

5 8 2
2 1
4 2
5 4
5 2
4 3
5 1
4 1
3 2

output

Copy

0
0
0
3
3
4
4
5

input

Copy

5 7 2
1 5
3 2
2 5
3 4
1 2
5 3
1 3

output

Copy

0
0
0
0
3
4
4

题意:
有n个人,m天,每天早上会有一对新的人建立朋友关系,
每天晚上有一次旅行,每一个人参加的条件是至少有k个他的朋友跟他一起参加旅行
问你每天晚上最大的参加的人数是多少?

解析:
一开始以为是找>k的团的数量,但后来发现并不是.....

这种情况1与另外3个点并不是团,但是1是可以取参加旅行的
然后去看了大佬们的代码.....
我看的那位大佬是用删边来做的。
我们本来是可以用每一个点的度数w来判断(w>k则去),一人能不能参加旅行的。
但是这里有一个问题是,一个人的朋友不一定有足够的朋友去参加旅行。
即一个点x连接了一个度数<k的点y,那么x的度数就无法判断了,
其实x连着y的边,对于x能否去旅行根本没有帮助,反而会影响x能否去旅行的判断。
那么我们把这条边,删掉,对应将x的度数-1。
那么我们既然发现有这些孤立点存在(度数<k)是无用的,那么我们把他们删掉就可以了。
并且随着删掉孤立点,新的孤立点也会产生(这些点其实就是伪孤立点,虽然度数>k,
但其实一样是无用的,只会影响判断答案),那么我们就需要用BFS来逐层删除孤立点。
(注意这里正是由于这些孤立点的存在,才无法用度数来判断一人能否去旅行,那么我们把这些
孤立点删掉之后,剩下的图里面的人是一定能去参加的,这个证明我具体也无法写出来,
感觉想一想应该是没问题的)

然后就是用离线来做,从后往前求答案
对于复杂度,因为每一条边最多遍历一次(删除),
那么其实就是一次BFS,复杂度为O(m+n)
 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define pb push_back 
#define mk make_pair
using namespace std;
typedef long long lli;
typedef pair<int,int> PII;


const lli MOD = 1e9+7;
const int MAXN = 2e5+10;

vector<int> edge[MAXN];
int deg[MAXN];
int query[MAXN][2];
queue<int> mq;
int k;
map<PII,int> mp;
int ans;
int res[MAXN];

void bfs()
{
	while(!mq.empty())
	{
		int u=mq.front();
		mq.pop();
		ans--;
		for(int i=0;i<edge[u].size();i++)
		{
			int v=edge[u][i];
			if(deg[v]<k) continue;  //状态标记,避免重复遍历,每一次只取删掉u只会,出现的新的孤立点
			if(mp[mk(u,v)]) continue;
			deg[v]--;
			if(deg[v]<k) mq.push(v);
		}
	}
}


int main()
{
	int n,m;
	scanf("%d%d%d",&n,&m,&k);
	int x,y;
	ans=n;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		edge[x].pb(y);
		edge[y].pb(x);
		deg[x]++;
		deg[y]++;
		query[i][0]=x;
		query[i][1]=y;

	}
	for(int i=1;i<=n;i++) if(deg[i]<k) mq.push(i);
	bfs();
	for(int i=m;i>=1;i--)
	{
		res[i]=ans;
		x=query[i][0];
		y=query[i][1];
		if(deg[x]<k||deg[y]<k); //这条边已经被删除了
		else
		{
			deg[x]--;
			deg[y]--;
			if(deg[x]<k) mq.push(x);
			if(deg[y]<k) mq.push(y);
			mp[mk(x,y)]=1;
			mp[mk(y,x)]=1;
			bfs();
		}
		
	}
	for(int i=1;i<=m;i++)
	{
		printf("%d\n",res[i]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37025443/article/details/82349880