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;
}