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

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

Note

In the first example,

  • 1,2,31,2,3 can go on day 33 and 44.

In the second example,

  • 2,4,52,4,5 can go on day 44 and 55.
  • 1,2,4,51,2,4,5 can go on day 66 and 77.
  • 1,2,3,4,51,2,3,4,5 can go on day 88.

In the third example,

  • 1,2,51,2,5 can go on day 55.
  • 1,2,3,51,2,3,5 can go on day 66 and 77.

题目大意:

    有N个人,M天,每天都有两个不认识的人成为朋友(朋友关系不可传递),一个人出来旅游的条件是他至少有K个朋友出去旅游,输出每一天最多有多少人出去旅游。

解法:

    可以想到的就是将整个图建好再倒着删边,看看每次删边能带来的变化,那么就得先求出整张图的答案:先将度数小于k的点加到队列,队列中的点表示无法旅游的人,如果该点不能旅游,相邻的点就少了一个能旅游的朋友,所以不断地更新相邻点的度数(度数>=K的不更新)最后剩余的没遍历到的点就是相邻至少K个点的集合了。知道最终答案后,记一个cnt的数组表示该点周围有多少个能旅游的人,当u-v这条边删掉,特判u,v是否仍然可以旅游,不能的话就DFS更新相邻点的cnt,注意已经不能旅游的点不用再跑了,这样每个点最多只会跑一次。

Accepted code

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;

#define sc scanf
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 2e5 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }

vector <pir> G[N];
int dep[N], d[N], n, m, k;
int vis[N], cnt[N], ans[N], tot;
bool vist[N];
pir eg[N];

void DFS(int x) {  // 遍历当前不能旅游的人是否会让相邻的人无法旅游
	vis[x] = 1, tot--;
	for (auto it : G[x]) {
		int v = it.first, id = it.second;
		if (vis[v] || vist[id])
			continue;
		cnt[v]--;
		if (cnt[v] < k)
			DFS(v);
	}
}

int main()
{
	cin >> n >> m >> k;
	for (int i = 1; i <= m; i++) {
		int u, v;
		sc("%d %d", &u, &v);
		G[u].push_back({ v, i });
		G[v].push_back({ u, i });
		dep[u]++, dep[v]++;
		eg[i] = { u, v };
	}
	for (int i = 1; i <= n; i++)
		d[i] = dep[i];
	queue <int> q;
	for (int i = 1; i <= n; i++) {   // 无法旅游的人
		if (d[i] < k)
			q.push(i), vis[i] = 1;
	}
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		for (auto it : G[u]) {
			int v = it.first;
			d[v]--;
			if (d[v] < k && !vis[v])  // 更新相邻点
				q.push(v), vis[v] = 1;
		}
	}
	for (int i = 1; i <= n; i++) {
		if (!vis[i])
			tot++;
		for (auto it : G[i]) {   // 相邻的可以旅游的人数
			if (!vis[it.first])
				cnt[i]++;
		}
	}
	ans[m] = tot;
	for (int i = m; i > 1; i--) {
		int u = eg[i].first, v = eg[i].second;  // 特判u,v是否可以旅游
		vist[i] = true;
		dep[u]--, dep[v]--;
		if (!vis[v])
			cnt[u]--;
		if (!vis[u])
			cnt[v]--;
		if (!vis[u] && cnt[u] < k)
			DFS(u);
		if (!vis[v] && cnt[v] < k)
			DFS(v);
		ans[i - 1] = tot;
	}
	for (int i = 1; i <= m; i++)
		printf("%d\n", ans[i]);

	return 0; // 改数组大小!!!用pair改宏定义!!!
}

猜你喜欢

转载自blog.csdn.net/weixin_43851525/article/details/109930680