思路:逆向并查集,逆向加入每一条边即可。在获取联通块数量的时候,直接判断新加入的边是否合并了两个集合,如果合并了说明联通块会减少一个,否则不变。
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; }
如有不当之处欢迎指出!