"China Eastcom Cup" Second Guangxi University Programming Contest - H - Antinomy and Il-MAG

Question is intended: to a directed graph, edges n-m points, each point right bit xi. U provisions from the point to the end of the specified one of the k points, many times you can go through the same point and the same edge, the maximum point on the right and find the path.

Solution: condensing point directly into the DAG, and dp when not directly applied to the father above, such as the following four points of the four sides of FIG:

4 4
1 2
1 3
2 4
3 4

Father added directly to the above will result in x [4] appears twice.

Note that this is actually a DAG, topology when attempting to update the value of his own to his father, his father retained the maximum value among all the sons on it.

And pay and WA, forgetting to consider the end point. Only when the son of the answer carries end point was to update the father, and set his father's answer is carrying the end point.

The 交又 T, Itago village Yes 个排 Josa heavy, 5e5 Kyozen non nlogn, good 吧, it's my mistake.

namespace SCC {
    const int MAXN = 5e5;

    int n;
    vector<int> G[MAXN + 5];
    vector<int> BG[MAXN + 5];

    int c1[MAXN + 5], cntc1;
    int c2[MAXN + 5], cntc2;
    int s[MAXN + 5], cnts;

    int n2;
    vector<int> V2[MAXN + 5];
    //vector<int> G2[MAXN + 5];
    vector<int> BG2[MAXN + 5];

    ll val[MAXN + 5];
    ll val2[MAXN + 5];
    bool ok[MAXN + 5];
    bool ok2[MAXN + 5];

    void Init(int _n) {
        n = _n;
        cntc1 = 0, cntc2 = 0, cnts = 0;
        for(int i = 1; i <= n; ++i) {
            G[i].clear();
            BG[i].clear();
            c1[i] = 0;
            c2[i] = 0;
            s[i] = 0;
            V2[i].clear();
            //G2[i].clear();
            BG2[i].clear();
            val[i] = 0;
            val2[i] = 0;
            ok[i] = 0;
            ok2[i] = 0;
        }
    }

    void AddEdge(int u, int v) {
        G[u].push_back(v);
        BG[v].push_back(u);
    }

    void dfs1(int u) {
        c1[u] = cntc1;
        for(int v : G[u]) {
            if(!c1[v])
                dfs1(v);
        }
        s[++cnts] = u;
    }

    void dfs2(int u) {
        V2[cntc2].push_back(u);
        val2[cntc2] += val[u];
        ok2[cntc2] |= ok[u];
        c2[u] = cntc2;
        for(int v : BG[u]) {
            if(!c2[v])
                dfs2(v);
        }
    }

    void Kosaraju() {
        for(int i = 1; i <= n; ++i) {
            if(!c1[i]) {
                ++cntc1;
                dfs1(i);
            }
        }

        for(int i = n; i >= 1; --i) {
            if(!c2[s[i]]) {
                ++cntc2;
                dfs2(s[i]);
            }
        }
    }

    void Build() {
        n2 = cntc2;
        for(int i = 1; i <= n2; ++i) {
            for(auto u : V2[i]) {
                for(auto v : G[u]) {
                    if(c2[v] != i) {
                        //G2[i].push_back(c2[v]);
                        BG2[c2[v]].push_back(i);
                    }
                }
            }
        }

        for(int i = 1; i <= n2; ++i) {
            //sort(G2[i].begin(), G2[i].end());
            //G2[i].erase(unique(G2[i].begin(), G2[i].end()), G2[i].end());
            //sort(BG2[i].begin(), BG2[i].end());
            //BG2[i].erase(unique(BG2[i].begin(), BG2[i].end()), BG2[i].end());
        }
    }


    void Solve(int u) {
        for(int i = n2; i >= 1; --i) {
            val[i] = 0;
            ok[i] = ok2[i];
        }
        for(int i = n2; i >= 1; --i) {
            ok[i] |= ok2[i];
            if(ok[i])
                val[i] += val2[i];
            for(auto &v : BG2[i]) {
                if(ok[i]) {
                    val[v] = max(val[v], val[i]);
                    ok[v] = 1;
                }
            }
        }
        printf("%lld\n", val[c2[u]]);
    }
}

void test_case() {
    int n, m;
    scanf("%d%d", &n, &m);
    SCC::Init(n);
    while(m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        SCC::AddEdge(u, v);
    }
    for(int i = 1; i <= n; ++i)
        scanf("%lld", &SCC::val[i]);
    int u, k;
    scanf("%d%d", &u, &k);
    while(k--) {
        int v;
        scanf("%d", &v);
        SCC::ok[v] = 1;
    }
    SCC::Kosaraju();
    SCC::Build();
    SCC::Solve(u);
}

Guess you like

Origin www.cnblogs.com/KisekiPurin2019/p/12006310.html