[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并不算特别的毒瘤?

posted @ 2019-05-26 13:31  蒟蒻SLS  阅读(297)  评论(0编辑  收藏  举报