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

  • 相关阅读:
    第4章.计算节点
    Eclipse插件ViPlugin2.X的破解方法
    金刚经
    js
    C++ 重写重载重定义区别
    string::substr()简介
    信息熵与二进制
    一个简单的条件概率问题
    HPLINUX hplinux 安装升级 至 jdk1.8
    linux 解压命令
  • 原文地址:https://www.cnblogs.com/QAQAQ/p/10925796.html
Copyright © 2020-2023  润新知