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\n", ans);
    }
    return 0;
}
时间: 2024-10-19 03:10:55

UVA11324-- The Largest Clique(SCC+DP)的相关文章

UVa11324 - The Largest Clique(DAG+DP+SCC)

Problem B: The Largest Clique Given a directed graph G, consider the following transformation. First, create a new graph T(G) to have the same vertex set as G. Create a directed edge between two vertices u and v in T(G) if and only if there is a path

uva11324 The Largest Clique --- 强连通+dp

给一个有向图G,求一个子图要求其中任意两点至少有一边可达, 问这个子图中最多含多少个顶点. 首先找SCC缩点建图,每个点的权值就是该点包含点的个数. 要求其中任意两点可达,实际上所有边只能同方向,不然一定有两点不可达, 这样题目又转换成求DAG图最长路的问题了. 然后从入度为0的点开始记忆化搜索,dp[i]表示以i为根最多包含多少点. #include <iostream> #include <cstring> #include <string> #include &l

UVA11324 The Largest Clique[强连通分量 缩点 DP]

UVA - 11324 The Largest Clique 题意:求一个节点数最大的节点集,使任意两个节点至少从一个可以到另一个 同一个SCC要选一定全选 求SCC 缩点建一个新图得到一个DAG,直接DP行了 这个新图不需要判重边,重边就是真实存在 // // main.cpp // 最大团 // // Created by Candy on 02/11/2016. // Copyright © 2016 Candy. All rights reserved. // #include <ios

UVA11324 The Largest Clique —— 强连通分量 + 缩点 + DP

题目链接:https://vjudge.net/problem/UVA-11324 题解: 代码一: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <sta

UVA-11324 The Largest Clique 【有向图强连通+缩点+DP】

题目链接:https://vjudge.net/problem/UVA-11324 题目大意:给定一张有向图G,求一个结点数最大的结点集,集合中每两个点都至少有一条路径相连(方向任意). 题解: 易知如果一个点被选择,则它所在强连通分量中的其他点也一定要选,如果不选,则其他点也不可选,因此先求出强连通分量,利用缩点创建出另一张有向图G2,每个结点的权值就是该强连通分量的结点数,再DP求解. 代码: 1 #include<bits/stdc++.h> 2 using namespace std;

UVAoj 11324 - The Largest Clique(tarjan + dp)

题意:给定一个有向图,寻找一个点数最大集合,使得这个集合中的任意两个点 u,v, 都有u->v 或者 v->u 或者u<==>v 思路:首先将强连通分量通过tarjan算法求出来,然后进行缩点,也就是每一个缩点 所组成的图就是一个DAG图!令每一个点的权值就是这个缩点所包含节点(也就是对应的 强连通分量的节点数目),因为强连通分量的任意的两个节点都是相互可达的,那么这个 缩点要么选要么不选,问题就转换成了DAG图上的最长路径! 1 #include<iostream>

UVA11324 The Largest Clique,有向图,最大团的结点数

点击打开链接 有向图 把强联通分量缩点后得到一个DAG,然后DP. </pre><pre name="code" class="cpp">#include <cstdio> #include <cstring> #include <algorithm> #include <stack> #include <vector> #include <queue> using na

UVA - 11324 The Largest Clique 强连通缩点+记忆化dp

题目要求一个最大的弱联通图. 首先对于原图进行强连通缩点,得到新图,这个新图呈链状,类似树结构. 对新图进行记忆化dp,求一条权值最长的链,每个点的权值就是当前强连通分量点的个数. /* Tarjan算法求有向图的强连通分量set记录了强连通分量 Col记录了强连通分量的个数. */ #include <iostream> #include<cstring> #include<cstdio> #include<string> #include<algo

uva 11324 The Largest Clique(图论-tarjan,动态规划)

Problem B: The Largest Clique Given a directed graph G, consider the following transformation. First, create a new graph T(G) to have the same vertex set as G. Create a directed edge between two vertices u and v in T(G) if and only if there is a path