zoukankan      html  css  js  c++  java
  • [ZJOI2007]最大半连通子图

    Description

    BZOJ1093

    Luogu2272

    Solution

    强连通一定半联通,所以就缩一下点。然后DAG上DP一下最长链就可以了,注意边表去一下重防止计数出错。

    Code

    一开始不会去重,所以蒯了别人的去重方法,代码可能有点丑。

    const int N = 100010;
    const int M = 1000010;
    
    struct Graph {
        int hd[N], to[M], nxt[M], cnt;
        void adde(int x, int y) {
            to[++cnt] = y;
            nxt[cnt] = hd[x];
            hd[x] = cnt;
        }
    } G;
    
    int n, m, ha, f[N], g[N];
    int w[N], dfn[N], low[N], dft, sta[N], top, ins[N], bel[N], tot, deg[N], ind[N];
    std::vector<int> DAG[N];
    std::queue<int> Q;
    
    void tarjan(int x) {
        ins[sta[++top] = x] = 1;
        dfn[x] = low[x] = ++dft;
        for (int i = G.hd[x]; i; i = G.nxt[i]) {
            int &v = G.to[i];
            if (!dfn[v]) {
                tarjan(v);
                low[x] = std::min(low[x], low[v]);
            } else if (ins[v])
                low[x] = std::min(low[x], dfn[v]);
        }
        if (dfn[x] == low[x]) {
            ++tot;
            int y;
            do {
                y = sta[top--];
                bel[y] = tot;
                ins[y] = 0;
                w[tot]++;
            } while (y != x);
        }
    }
    
    void main() {
        n = read(), m = read(), ha = read();
        for (int i = 1, x, y; i <= m; ++i) {
            x = read(), y = read();
            G.adde(x, y);
        }
        for (int i = 1; i <= n; ++i)
            if (!dfn[i]) tarjan(i);
        for (int i = 1; i <= n; ++i) {
            for (int j = G.hd[i]; j; j = G.nxt[j])
                if (bel[G.to[j]] != bel[i]) {
                    DAG[bel[i]].push_back(bel[G.to[j]]);
                }
        }
        for (int i = 1; i <= tot; ++i) {
            std::sort(DAG[i].begin(), DAG[i].end());
            deg[i] = std::unique(DAG[i].begin(), DAG[i].end()) - DAG[i].begin();
            for (int j = 0; j < deg[i]; ++j) ind[DAG[i][j]]++;
            f[i] = w[i];
            g[i] = 1;
        }
        for (int i = 1; i <= tot; ++i)
            if (!ind[i]) Q.push(i);
        while (!Q.empty()) {
            int x = Q.front();
            Q.pop();
            for (int i = 0; i < deg[x]; ++i) {
                int &y = DAG[x][i];
                if (f[x] + w[y] > f[y])
                    f[y] = f[x] + w[y], g[y] = g[x];
                else if (f[x] + w[y] == f[y])
                    g[y] = (g[y] + g[x]) % ha;
                if (--ind[y] == 0) Q.push(y);
            }
        }
        int ans1 = 0, ans2 = 0;
        for (int i = 1; i <= tot; ++i)
            if (f[i] > ans1) {
                ans1 = f[i];
                ans2 = g[i];
            } else if (f[i] == ans1) {
                ans2 = (ans2 + g[i]) % ha;
            }
        printf("%d %d
    ", ans1, ans2);
    }
    
  • 相关阅读:
    canvas
    canvas -矩形
    canvas
    requestAnimationFrame
    flex in css
    让 .vue 支持 atom
    前端应该知道的基础知识汇总
    css伪类总结
    制作滑动门菜单
    页面布局中遇到菱形图片时的处理办法
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/bzoj1093.html
Copyright © 2011-2022 走看看