1. 程式人生 > >【codefroces 1037 E Trips】【圖論】【逆向思維】【好】【度大於等於k的最大子圖】

【codefroces 1037 E Trips】【圖論】【逆向思維】【好】【度大於等於k的最大子圖】

【連結】

【題意】

有n個人,一開始都不是朋友,m天每天都會有x,y成為朋友,現在他們有trip,只有他們出去玩的朋友數大於等於k才能出去,求每天出去最多的人數。朋友關係不具有傳遞性

【思路】

用set維護圖,並記錄與點相連的邊集。如果圖從無到有建邊,那麼每加入一條邊會導致與端點有邊的所有點都需要修改,並且不容易判斷,計數每天最大的size,那麼我們可能逆向思維。先建好全圖,將不符合的點刪去。從後往前刪邊,只需要刪去邊集與點集,size的大小就是答案了

【程式碼】

#include<bits./stdc++.h>
using namespace std;
const int maxn = 2e5 + 6;
struct node {
	int x, y, ans;
}t[maxn];

set<int>st;
set<int>v[maxn];
int n, m, k;

void del(int x) {
	if (v[x].size() < k&&st.erase(x)) {
		for (auto &y : v[x]) {
			v[y].erase(x);
			del(y);
		}
	}
}

int main() {
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 1; i <= m; i++) {
		scanf("%d%d", &t[i].x, &t[i].y);
		v[t[i].x].insert(t[i].y);
		v[t[i].y].insert(t[i].x);
	}
	for (int i = 1; i <= n; i++) {
		st.insert(i);
	}
	for (int i = 1; i <= n; i++) {
		del(i);
	}
	for (int i = m; i; i--) {
		t[i].ans = st.size();
		if (st.size() == 0)break;
		v[t[i].x].erase(t[i].y);
		v[t[i].y].erase(t[i].x);
		del(t[i].x);
		del(t[i].y);
	}
	for (int i = 1; i <= m; i++) {
		printf("%d\n", t[i].ans);
	}
}