zoukankan      html  css  js  c++  java
  • 【强连通分量+缩点+DAGdp/拓扑排序】UVA11324 The Largest Clique

    UVA11324 The Largest Clique

    思路:强连通分量缩点转化DAG+DAG上的DP

    解法一:记忆化搜索

    #define mem(a,n) memset(a,n,sizeof(a))
    #define f(i,a,b) for(int i=a;i<=b;i++)
    #define af(i,a,b) for(int i=a,i>=b;i--)
    
    using namespace std;
    typedef long long LL;
    const int INF = 20010509;
    const int maxn = 1e3 + 100;
    const int maxm = 5e4 + 100;
    
    stack<int> s;
    
    int dfs_clock, scc_cnt;
    int dfn[maxn], low[maxn], sccno[maxn];
    int head[maxn], headnew[maxn], cnt = 0;
    int n, m;
    int val[maxn], dp[maxn];
    
    struct Edge {
        int next, to;
    }e[maxm], enew[maxm];
    
    void add(int from, int to, Edge eset[], int head[]) {
        cnt++;
        eset[cnt].next = head[from];
        eset[cnt].to = to;
        head[from] = cnt;
    }
    
    void dfs(int u) {
        dfn[u] = low[u] = ++dfs_clock;
        s.push(u);
        for (int i = head[u]; i; i = e[i].next) {
            int v = e[i].to;
            if (!dfn[v]) {
                dfs(v);
                low[u] = min(low[u], low[v]);
            }
            else if (!sccno[v]) {
                low[u] = min(low[u], dfn[v]);
            }
        }
        if (low[u] == dfn[u]) {
            scc_cnt++;
            while (1) {
                int x = s.top(); s.pop();
                sccno[x] = scc_cnt;
                val[scc_cnt]++;
                if (x == u) break;
            }
        }
    }
    
    void find_scc(int n) {
        while (!s.empty()) s.pop();
        dfs_clock = scc_cnt = 0;
        mem(sccno, 0);
        mem(dfn, 0);
        mem(low, 0);
        for (int i = 1; i <= n; i++) {
            if (!dfn[i]) dfs(i);
        }
    }
    
    int Dp(int i) {
      //实际上是记忆化搜索
        if (dp[i]) return dp[i];
        dp[i] = val[i];
        for (int j = headnew[i]; j; j = enew[j].next) {
            int v = enew[j].to;
            dp[i] = max(dp[i], Dp(v) + val[i]);
        }
        return dp[i];
    }
    
    void init() {
        cnt = 0;
        mem(e, 0);
        mem(enew, 0);
        mem(headnew, 0);
        mem(head, 0);
        mem(val, 0);
        mem(dp, 0);
    }
    int main(){
        int t; cin >> t; while (t--) {
            init();
            cin >> n >> m;
            for (int i = 1; i <= m; i++) {
                int u, v; cin >> u >> v;
                add(u, v, e, head);
            }
            find_scc(n);
            cnt = 0;
            //将SCC都缩成一个点,建立新图
            for (int u = 1; u <= n; u++) {
                for (int i = head[u]; i; i = e[i].next) {
                    int v = e[i].to;
                    if (sccno[u] != sccno[v]) {
                        add(sccno[u], sccno[v], enew, headnew);
                    }
                }
            }
            int ans = 0;
            for (int i = 1; i <= scc_cnt; i++) {
                ans = max(ans, Dp(i));
            }
            cout << ans << endl;
        }
        return 0;
    }
    

    解法二:拓扑排序+DP

  • 相关阅读:
    【USACO2017JAN】 Promotion Counting
    【POJ 3468】 A Simple Problem with Integers
    【HDU 1754】 I Hate It
    【Codeforces 20C】 Dijkstra?
    【POJ 2407】 Relatives
    BZOJ5249 九省联考2018IIIDX(线段树+贪心)
    BZOJ5251 八省联考2018劈配(网络流)
    BZOJ4200 NOI2015小园丁与老司机(动态规划+上下界网络流)
    BZOJ3876 AHOI/JSOI2014支线剧情(上下界网络流)
    LOJ117 有源汇有上下界最小流(上下界网络流)
  • 原文地址:https://www.cnblogs.com/streamazure/p/13816476.html
Copyright © 2011-2022 走看看