molarsu @ 2021-12-27 20:39:11
#include<iostream>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int maxn = 400005;
int n, m, a[maxn], b[maxn], k, usa[maxn], x[maxn], pre[maxn],cnt, head[maxn], ecnt, ans[maxn];
stack<int> destory;
int fd(int y) {
if (pre[y] == y) return y;
return y = fd(pre[y]);
}
void hb(int aa, int bb) {
aa = fd(aa), bb = fd(bb);
pre[bb] = aa;
}
struct edge {
int x, nxt;
}e[maxn << 1];
void add_edge(int u, int v) {
ecnt++;
e[ecnt].nxt = head[u];
e[ecnt].x = v;
head[u] = ecnt;
}
int cntt(int xx) {
set<int> s;
for (int i = head[xx]; i; i = e[i].nxt) {
int u = e[i].x;
if (!usa[u]) {
s.insert(fd(u));
}
}
return s.size();
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++)scanf("%d %d", &a[i], &b[i]),add_edge(a[i],b[i]),add_edge(b[i],a[i]);
for (int j = 0; j < n; j++) {
pre[j] = j;
}
scanf("%d", &k);
for (int i = 1; i <= k; i++) {
scanf("%d", &x[i]);
usa[x[i]] = true;
}
for (int i = 0; i < n; i++) {
if (!usa[a[i]] && !usa[b[i]]) {
hb(a[i], b[i]);
}
}
for (int i = 0; i < n; i++) {
if (!usa[i] && fd(i) == i)cnt++;
}
ans[k + 1] = cnt;
for (int j = k; j >= 1; j--) {
int tmp = x[j];
usa[tmp] = false;
bool f = false;
int cnt1 = cntt(tmp);
for (int i = head[tmp]; i; i = e[i].nxt) {
int u = e[i].x;
int tmpp = fd(u);
if (!usa[u]) {
hb(u, tmp);
f = true;
}
if (fd(u) != tmpp)cnt--;
}
if (!f)cnt++;
else cnt -= cnt1, cnt++;
ans[j] = cnt;
}
for (int i = 1; i <= k + 1; i++)cout << ans[i] << endl;
return 0;
}
反向加边的思路, 一直是40分 第五个点还没输出 求救
by molarsu @ 2021-12-27 20:40:35
评测链接
by molarsu @ 2021-12-28 09:02:59
发现两个问题,head没初始化,编号有零没注意,使用了直接判断i的真假
by molarsu @ 2021-12-31 10:44:28
此贴终,出现的问题首先是并查集优化写错了, 第二个是 有一个for 循环的条件写错了