• UVA11324-- The Largest Clique(SCC+DP)


    题目链接


    题意:给出一张有向图,求一个结点数最大的结点集,使得该结点集中随意两个结点u和v满足:要么u能够到到v,要么v能够到达u(u和v能够互相到达)

    思路:我们能够缩点,用Tarjan求出全部强连通分量,让每一个SCC的权值等于它的结点个数。因为SCC图是有一个DAG,使用DP求解。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <stack>
    #include <algorithm>
    
    using namespace std;
    
    const int MAXN = 1005;
    
    vector<int> g[MAXN], scc[MAXN], G[MAXN];
    stack<int> s;
    int pre[MAXN], lowlink[MAXN], sccno[MAXN], sccnum[MAXN], dfs_clock, scc_cnt; 
    int d[MAXN];
    int n, m;
    
    int Tarjan(int u) {
        lowlink[u] = pre[u] = ++dfs_clock;
        s.push(u);
        for (int i = 0; i < g[u].size(); i++) {
            int v = g[u][i]; 
            if (!pre[v]) {
                Tarjan(v); 
                lowlink[u] = min(lowlink[v], lowlink[u]);
            } 
            else if (!sccno[v]) {
                lowlink[u] = min(lowlink[u], pre[v]); 
            }
        }
        if (lowlink[u] == pre[u]) {
            scc_cnt++;
            for (;;) {
                int x = s.top(); 
                s.pop();
                sccno[x] = scc_cnt;
                sccnum[sccno[x]]++;
                if (x == u) break;
            } 
        }
    }
    
    void find_scc() {
        memset(pre, 0, sizeof(pre));
        memset(lowlink, 0, sizeof(lowlink));
        memset(sccno, 0, sizeof(sccno));
        memset(sccnum, 0, sizeof(sccnum));
        dfs_clock = scc_cnt = 0;
        for (int i = 0; i < n; i++)
            if (!pre[i])
                Tarjan(i);
    }
    
    int dp(int i) {
        int& ans = d[i]; 
        if (ans > 0) return ans;
        ans = sccnum[i];
        for (int j = 0; j < G[i].size(); j++) {
            int v = G[i][j];
            ans = max(ans, dp(v) + sccnum[i]);
        }
        return ans;
    }
    
    int main() {
        int cas;
        scanf("%d", &cas);
        while (cas--) {
            scanf("%d%d", &n, &m);
            for (int i = 0; i < n; i++)
                g[i].clear();
            int u, v;
            for (int i = 0; i < m; i++) {
                scanf("%d%d", &u, &v); 
                u--;
                v--;
                g[u].push_back(v);
            }
    
            find_scc();
    
            memset(d, -1, sizeof(d));
            memset(G, 0, sizeof(G));
            for (int u = 0; u < n; u++) {
                for (int i = 0; i < g[u].size(); i++) {
                    int v = g[u][i]; 
                    if (sccno[u] != sccno[v]) 
                        G[sccno[u]].push_back(sccno[v]); 
                } 
            }        
    
            int ans = 0;
            for (int i = 1; i <= scc_cnt; i++) 
                ans = max(ans, dp(i));
    
            printf("%d
    ", ans);
        }
        return 0;
    }


  • 相关阅读:
    几种典型程序Button处理代码的定位转
    sql server索引使用效率评估
    sql server查询死锁的sql语句
    SqlServer 查询计划
    批量删除Word中的回车符号
    数据在机器中的表示
    win32汇编窗口程序设计[05]获取屏幕分辨率
    清理win7任务栏图标
    Win32汇编窗口程序设计[06]—“Hello Win32ASM”改进版
    关于ASCII码的几点小结
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4293698.html
Copyright © 2020-2023  润新知