zoukankan      html  css  js  c++  java
  • Luogu 3627 [APIO2009]抢掠计划

    不爽。

    为什么tarjan能爆栈啊

    十分显然的缩点,给缩点之后的点连上权值为后一个点集权值的有向边,然后spfa跑最长路。

    注意一开始$dis_{st}$应该等于$st$这个集合的权值。

    时间复杂度$O(能过)$。

    非递归版的tarjan可以学习一下。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <stack>
    using namespace std;
    
    const int N = 8e5 + 5;
    const int inf = 0x3f3f3f3f;
    
    int n, m, st, edNum, dfsc = 0, dfn[N], low[N], bel[N];
    int tot = 0, head[N], scc = 0, a[N], val[N], dis[N];
    int top = 0, sta[N], inx[N << 1], iny[N << 1];
    bool vis[N], isEnd[N], sccEnd[N]; 
    stack <int> S;
    
    struct Edge {
        int to, nxt, val;
    } e[N << 1];
    
    inline void add(int from, int to, int v = 0) {
        e[++tot].to = to;
        e[tot].val = v;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    inline void read(int &X) {
        X = 0;
        char ch = 0;
        int op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline int min(int x, int y) {
        return x > y ? y : x;
    }
    
    inline void chkMax(int &x, int y) {
        if(y > x) x = y;
    }
    
    /*void tarjan(int x) {
        dfn[x] = low[x] = ++dfsc;
        sta[++top] = x, vis[x] = 1;
         for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(!dfn[y]) tarjan(y), low[x] = min(low[x], low[y]);
            else if(vis[y]) low[x] = min(low[x], dfn[y]);
        }
        
        if(low[x] == dfn[x]) {
            ++scc;
            for(; sta[top + 1] != x; top--) {
                sccEnd[scc] |= isEnd[sta[top]];
                bel[sta[top]] = scc;
                val[scc] += a[sta[top]];
                vis[sta[top]] = 0;
            }
        }
    }   */
    
    void tarjan(int fir) {
        low[fir] = dfn[fir] = ++dfsc;
        sta[++top] = fir, vis[fir] = 1;
        S.push(fir);
        for(; !S.empty(); ) {
            int x = S.top(); 
            for(int i = head[x]; i; i = e[i].nxt) {
                int y = e[i].to;
                if(!dfn[y]) {
                    dfn[y] = low[y] = ++dfsc;
                    sta[++top] = y, vis[y] = 1;
                    S.push(y);
                    break;
                }
            }
            
            if(x == S.top()) {
                for(int i = head[x]; i; i = e[i].nxt) {
                    int y = e[i].to;
                    if(dfn[y] > dfn[x]) low[x] = min(low[x], low[y]);
                    else if(vis[y]) low[x] = min(low[x], dfn[y]);
                }
                
                if(low[x] == dfn[x]) {
                    ++scc;
                    for(; sta[top + 1] != x; top--) {
                        sccEnd[scc] |= isEnd[sta[top]];
                        bel[sta[top]] = scc;
                        val[scc] += a[sta[top]];
                        vis[sta[top]] = 0;
                    }
                }
                
                S.pop();
            }
        }
    }
    
    queue <int> Q;
    void spfa() {
        memset(dis, 0x3f, sizeof(dis)); dis[st] = -val[st];
        Q.push(st); vis[st] = 1;
        for(; !Q.empty(); ) {
            int x = Q.front(); Q.pop();
            vis[x] = 0;
            for(int i = head[x]; i; i = e[i].nxt) {
                int y = e[i].to;
                if(dis[y] > dis[x] + e[i].val) {
                    dis[y] = dis[x] + e[i].val;
                    if(!vis[y]) Q.push(y), vis[y] = 1;
                }
            }
        }
    }
    
    int main() {
        read(n), read(m);
        for(int x, y, i = 1; i <= m; i++) {
            read(x), read(y);
            inx[i] = x, iny[i] = y;
            add(x, y);
        }
        for(int i = 1; i <= n; i++) read(a[i]);
        read(st), read(edNum);
        for(int x, i = 1; i <= edNum; i++) read(x), isEnd[x] = 1;
        
        for(int i = 1; i <= n; i++)
            if(!dfn[i]) tarjan(i);
        
    /*    for(int i = 1; i <= n; i++)
            printf("%d ", bel[i]);
        printf("
    ");
        for(int i = 1; i <= n; i++)
            printf("%d ", val[i]);
        printf("
    ");   */
            
        tot = 0; memset(head, 0, sizeof(head));
        for(int i = 1; i <= m; i++) {
            if(bel[inx[i]] == bel[iny[i]]) continue;
            add(bel[inx[i]], bel[iny[i]], -val[bel[iny[i]]]);
        }
        
        st = bel[st];
        spfa();
        
        int ans = 0;
        for(int i = 1; i <= scc; i++)
            if(sccEnd[i] && dis[i] != inf) chkMax(ans, -dis[i]);
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    CCF CSP 题解
    CCF CSP 2019032 二十四点
    CCF CSP 2018121 小明上学
    CCF CSP 2019092 小明种苹果(续)
    CCF CSP 2019091 小明种苹果
    CCF CSP 2019121 报数
    CCF CSP 2019031 小中大
    CCF CSP 2020061 线性分类器
    CCF CSP 2020062 稀疏向量
    利用国家气象局的webservice查询天气预报(转载)
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9529574.html
Copyright © 2011-2022 走看看