HDU - 4496 City 逆向并查集

时间:2022-08-12 05:52:55

思路:逆向并查集,逆向加入每一条边即可。在获取联通块数量的时候,直接判断新加入的边是否合并了两个集合,如果合并了说明联通块会减少一个,否则不变。

AC代码

#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 10000 + 5;
int p[maxn], vis[maxn];
PI a[maxn*10];

int find(int x) {
	return p[x] == x ? x : p[x] = find(p[x]);
}

bool unionset(int x, int y) {
	int rx = find(x), ry = find(y);
	if(rx != ry) {
		p[rx] = ry;
		return true;
	}
	return false;
}

int main() {
	int n, m;
	while(scanf("%d%d", &n, &m) == 2) {
		for(int i = 0; i < n; ++i) p[i] = i;
		int u, v;
		for(int i = 0; i < m; ++i) {
			scanf("%d%d", &u, &v);
			a[i] = make_pair(u, v);
		}
		stack<int>ans;
		for(int i = m-1; i >= 0; --i) {
			ans.push(n);
			if(unionset(a[i].first, a[i].second)) --n;
		}
		while(!ans.empty()) {
			printf("%d\n", ans.top());
			ans.pop();
		}
	}
	return 0;
} 

如有不当之处欢迎指出!