zoukankan      html  css  js  c++  java
  • AcWing 368. 银河

    原本是一个差分约束的问题,但是由于数据过大可能导致(spfa)被卡,而由于这道题的边权只有(0,1)两种,比较特殊,所以使用(tarjan)求连通分量,缩点,递推的方式也能完成,时间复杂度是线性的。

    用差分约束的思路根据不等式建图,然后从(0)号节点开始求单源最长路,若图中存在正环那么无解。否则,从(0)到每个节点的最长路的长度就是对应最小合法亮度。在这道题中,建立的图中边权只有(0,1)两种。同时,如果图中存在一个环,那么环上的边的长度必然全是(0)才行,不然就说明存在正环,即无解。

    而我们知道,环又一定是在强连通分量中的,所以我们可以求图的强连通分量,只要强连通分量内部存在长度为(1)的点,那么就无解。

    如果有解,因为每个强连通分量内部没有边权为(1)的边,全(0),所以对于一个强连通分量中的点来说,从源点到强连通分量的距离就等于到强连通分量中点的距离,所以进行缩点,建立新图,由于(tarjan)算法后,强连通分量编号的逆序就是拓扑序,所以直接递推求距离,然后答案就是(res += Size[i] * dist[i])

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1E5 + 10, M = 6E5 + 10;
    
    typedef long long LL;
    
    int h[N], hs[N], e[M], ne[M], w[M], idx;
    int dfn[N], low[N], timestamp;
    int stk[N], top;
    bool in_stk[N];
    int id[N], scc_cnt, scc_size[N];
    int dist[N];
    int n, m;
    
    void add(int h[], int a, int b, int c) {
        e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
    }
    
    void tarjan(int u) {
        dfn[u] = low[u] = ++timestamp;
        stk[++top] = u, in_stk[u] = true;
        for (int i = h[u]; i != -1; i = ne[i]) {
            int j = e[i];
            if (!dfn[j]) {
                tarjan(j);
                low[u] = min(low[u], low[j]);
            } else if (in_stk[j]) low[u] = min(low[u], dfn[j]);
        }
        
        if (dfn[u] == low[u]) {
            ++scc_cnt;
            int y;
            do {
                y = stk[top--];
                in_stk[y] = false;
                id[y] = scc_cnt;
                scc_size[scc_cnt]++;
            } while(y != u);
        }
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        memset(h, -1, sizeof h);
        memset(hs, -1, sizeof h);
        
        for (int i = 1; i <= n; i++) add(h, 0, i, 1);
        
        while (m--) {
            int t, a, b;
            scanf("%d%d%d", &t, &a, &b);
            if (t == 1) add(h, b, a, 0), add(h, a, b, 0);
            else if (t == 2) add(h, a, b, 1);
            else if (t == 3) add(h, b, a, 0);
            else if (t == 4) add(h, b, a, 1);
            else if (t == 5) add(h, a, b, 0);
        }
        
        tarjan(0);
        //建立新图
        bool success = true;
        for (int i = 0; i <= n; i++) {
            for (int j = h[i]; j != -1; j = ne[j]) {
                int k = e[j];
                int a = id[i], b = id[k];
                //在一个强联通分量
                if (a == b) {
                    //说明存在正环
                    if (w[j] > 0) {
                        success = false;
                        break;
                    }
                } else add(hs, a, b, w[j]);
            }
        }
        
        if (!success) puts("-1");
        else {
            for (int i = scc_cnt; i; i--) {
                for (int j = hs[i]; j != -1; j = ne[j]) {
                    int k = e[j];
                    dist[k] = max(dist[k], dist[i] + w[j]);
                }
            }
            
            LL res = 0;
            for (int i = 1; i <= scc_cnt; i++) res += (LL) dist[i] * scc_size[i];
            
            printf("%lld
    ", res);
        }
        
        return 0;
    }
    
  • 相关阅读:
    UVA1349 Optimal Bus Route Design 最优巴士路线设计
    POJ3565 Ants 蚂蚁(NEERC 2008)
    UVA1663 Purifying Machine 净化器
    UVa11996 Jewel Magic 魔法珠宝
    NEERC2003 Jurassic Remains 侏罗纪
    UVA11895 Honorary Tickets
    gdb调试coredump(使用篇)
    使用 MegaCLI 检测磁盘状态并更换磁盘
    员工直接坦诚直来直去 真性情
    山东浪潮超越3B4000申泰RM5120-L
  • 原文地址:https://www.cnblogs.com/ZhengLijie/p/15067986.html
Copyright © 2011-2022 走看看