D-City
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 3933 Accepted Submission(s): 1417
One day Luxer went to D-city. D-city has N D-points and M D-lines. Each D-line connects exactly two D-points. Luxer will destroy all the D-lines. The mayor of D-city wants to know how many connected blocks of D-city left after Luxer destroying the first K D-lines in the input.
Two points are in the same connected blocks if and only if they connect to each other directly or indirectly.
Then following M lines each containing 2 space-separated integers u and v, which denotes an D-line.
Constraints:
0 < N <= 10000
0 < M <= 100000
0 <= u, v < N.
逆向看,原来有t个连通分支,然后不断地往里面加边,如果边的两个端点原来不在同一个连通分支里面,那么把它们两个的连通分支合为一个,且t = t - 1,如果原来就在同一个连通分支里面,对t不操作,用并查集来判断是否在同一个连通分支里面以及合并操作,用一个数组记录t的值用于最后输出,注意逆向加边的时候,最后会多个t = 1,最后要去掉
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <set>
using namespace std;
const int maxn = 10005, maxm = 100005;
int T, n, m;
int f[maxn], ans[maxm], len;
struct Edge {
int u, v;
Edge() {}
Edge(int u, int v) : u(u), v(v) {}
}edges[maxm];
int getf(int x) {
return x == f[x] ? x : f[x] = getf(f[x]);
}
void Merge(int x, int y) {
int u = getf(x), v = getf(y);
if (u != v) {
if (u < v) {
f[v] = u;
}
else {
f[u] = v;
}
}
}
int main()
{
while (~scanf("%d%d", &n, &m)) {
for (int i = 0; i < n; i++) {
f[i] = i;
}
for (int i = 0; i < m; i++) {
scanf("%d%d", &edges[i].u, &edges[i].v);
}
int t = n;
ans[0] = n;
len = 1;
for (int i = m - 1; i >= 0; i--) {
int u, v, x, y;
u = edges[i].u;
v = edges[i].v;
x = getf(u);
y = getf(v);
if (x != y) {
t -= 1;
}
ans[len++] = t;
Merge(u, v);
}
for (int i = len - 2; i >= 0; i--) {
printf("%d\n", ans[i]);
}
}
return 0;
}