[SHOI2014]神奇化合物
看一眼就知道是动态图吖(口胡.jpg
以上纯属假消息。。。
其实这题是一道明显的技(xia)巧(gao)题,我们发现询问数远小于边数,这表明有一些边是一直存在的。。于是我们可以离线做,,对一直存在的边组成的图进行缩点,然后就开始暴力维护添边和删边即可。。注意用计数器纪录一下重边,而不是不停的加边即可。。
最好再判一下自环,,有人已经造出有自环的hack数据惹。。似乎还卡掉了不少人。。
#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
int lst[5005], to[100005], pre[100005], tot,in[5005][5005], iu[200005], iv[200005], qu[10005], qv[10005], idx[5005], fa[5005], cnt;
char tp[10005];
bool vis[5005], del[100005];
map<int, pair<int, int> > edge[5005];
inline void add_edge(int u, int v) {
if (edge[u].count(v) && edge[u][v].first) {
edge[u][v].first++;
return;
}
edge[u][v] = mp(1, tot);
to[tot] = v;
pre[tot] = lst[u];
lst[u] = tot++;
}
int findf(int u) {
if (u == fa[u]) return u;
return fa[u] = findf(fa[u]);
}
void dfs(int u) {
vis[u] = true;
for (int i = lst[u]; ~i; i = pre[i]) {
if (!del[i] && !vis[to[i]])
dfs(to[i]);
}
}
int main() {
memset(lst, -1, sizeof lst);
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++) {
scanf("%d%d", iu + i, iv + i);
in[--iu[i]][--iv[i]] = 1;
in[iv[i]][iu[i]] = 1;
}
int q;
scanf("%d", &q);
for (int i = 0; i < q; i++) {
scanf(" %c", tp + i);
if (tp[i] != 'Q') {
scanf("%d%d", qu + i, qv + i);
qu[i]--;
qv[i]--;
if (tp[i] == 'D') in[qu[i]][qv[i]] = in[qv[i]][qu[i]] = 0;
}
}
for (int i = 0; i < n; i++) fa[i] = i;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (in[i][j]) fa[findf(i)] = findf(j);
for (int i = 0; i < n; i++)
if (findf(i) == i) idx[i] = cnt++;
for (int i = 0; i < n; i++) idx[i] = idx[fa[i]];
memset(in, false, sizeof in);
for (int i = 0; i < m; i++) {
int u = idx[iu[i]], v = idx[iv[i]];
if (u != v) {
add_edge(u, v);
add_edge(v, u);
}
}
for (int i = 0; i < q; i++)
if (tp[i] == 'Q') {
memset(vis, false, cnt);
int ans = 0;
for (int j = 0; j < cnt; j++) {
if (!vis[j]) {
ans++;
dfs(j);
}
}
printf("%d\n", ans);
} else if (tp[i] == 'A') {
int u = idx[qu[i]], v = idx[qv[i]];
if (u != v) {
add_edge(u, v);
add_edge(v, u);
}
} else {
int u = idx[qu[i]], v = idx[qv[i]];
if (u == v) continue;
edge[u][v].first--;
edge[v][u].first--;
if (!edge[u][v].first) del[edge[u][v].second] = del[edge[v][u].second] = true;
}
}
个人感觉shoi并不算特别的毒瘤?