UVA 11324 The Largest Clique (强联通+DP)

来源:互联网 发布:XP电脑的mac地址怎么查 编辑:程序博客网 时间:2024/05/21 07:07

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=54643#problem/C


题意:给一张有向图,求一个结点数最大的结点集,使得该集合任意两节点U和V满足:要么U能到V,要么V能到U,互相能达也行


思路:同一个强联通分量里的点要么都选,要么都不选,故先缩点,那么每个SCC结点的权值等于它的结点数,题目便转化为求SCC图上权最大的路径,DP即可求解


#include <iostream>#include <cstring>#include <cstdio>#include <string>#include <algorithm>#include <vector>using namespace std;const int maxn = 2020;const int maxm = 100010;struct node{    int to, nxt;} e[maxm];int head[maxn], ecnt, num[maxn];int low[maxn], dfn[maxn], sta[maxn], top, bel[maxn], block, idx;bool insta[maxn];int n, m;void add(int u, int v){    e[ecnt].to = v;    e[ecnt].nxt = head[u];    head[u] = ecnt++;}void tarjan(int u){    int v;    low[u] = dfn[u] = ++idx;    sta[top++] = u;    insta[u] = true;    for(int i = head[u]; ~i; i = e[i].nxt)    {        v = e[i].to;        if(!dfn[v])        {            tarjan(v);            low[u] = min(low[u], low[v]);        }        else            if(insta[v] && low[u] > dfn[v])                low[u] = dfn[v];    }    if(low[u] == dfn[u])    {        block++;        do        {            v = sta[--top];            insta[v] = false;            bel[v] = block;            num[block]++;        }        while(v != u);    }}void solve(){    top = block = idx = 0;    memset(insta, 0, sizeof(insta));    memset(bel, -1, sizeof(bel));    memset(dfn, 0, sizeof(dfn));    memset(num, 0, sizeof(num));    for (int i = 1; i <= n; i++)        if (!dfn[i])            tarjan(i);}vector<int> g[maxn];int dp[maxn], cnt[maxn];int dfs_dag(int u){    if(dp[u] > 0) return dp[u];    dp[u] = cnt[u];    for(int i = 0; i < g[u].size(); i++)    {        int v = g[u][i];        dp[u] = max(dp[u], dfs_dag(v) + cnt[u]);    }    return dp[u];}int main(){    int t;    scanf("%d", &t);    while(t--)    {        int u, v;        scanf("%d%d", &n, &m);        memset(head, -1, sizeof(head));        ecnt = 0;        for(int i = 0; i < m; i++)        {            scanf("%d%d", &u, &v);            add(u, v);        }        solve();        for(int i = 0; i <= block; i++)            g[i].clear();        memset(cnt, 0, sizeof(cnt));        for(int i = 1; i <= n; i++)        {            u = bel[i];            cnt[u]++;            for(int j = head[i]; j != -1; j = e[j].nxt)            {                v = bel[e[j].to];                if(u == v) continue;                g[u].push_back(v);            }        }        int ans = 0;        memset(dp, 0, sizeof(dp));        for(int i = 1; i <= block; i++)            ans = max(ans, dfs_dag(i));        printf("%d\n", ans);    }}



0 0
原创粉丝点击