zoukankan      html  css  js  c++  java
  • Uva 11324 最大团

    题目链接:http://vjudge.net/contest/141990#problem/B

    题意:

    给一张有向图G,求一个结点集数最大的结点集,是的该结点集中任意两个结点 u 和 v,满足: 要么 u 能到达 v,要么 v 能到达 u 或者 u 和 v 可以互达 ;

    这个和有向强连通图很像,连通方式改了,强连通分量是 任意 两点 之间 都可以互达。可以发现一个强连通分量 ,要么全选,要么全部选。

    思路:

    把一个强连通分量看成一个结点,这个结点有权值,是他的大小,把每个强连通分量看成一个结点,这样 SCC 图就出来了,SCC图 他是一个有向无环图 DAG。

    于是就可以用 dp 来做。

    坑点:(数据有可能一个结点都没有)

    #include <bits/stdc++.h>
    using namespace std;
    
    const int Maxn = 1000 + 10;
    
    vector<int> G[Maxn];
    int pre[Maxn];
    int lowlink[Maxn];
    int sccno[Maxn];
    int dfs_clock;
    int scc_cnt;
    int n,m;
    
    stack<int> S;
    
    void dfs(int u)
    {
        pre[u] = lowlink[u] = ++dfs_clock;
        S.push(u);
        for(int i = 0; i < G[u].size(); i++)
        {
            int v = G[u][i];
            if(!pre[v])
            {
                dfs(v);
                lowlink[u] = min(lowlink[u], lowlink[v]);
            }
            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;
                if(x == u) break;
            }
        }
    }
    
    
    void find_scc(int)
    {
        dfs_clock = scc_cnt = 0;
        memset(pre,0,sizeof(pre));
        memset(sccno,0,sizeof(sccno));
    
        for(int i=0; i<n; i++)
        {
            if(!pre[i])
                dfs(i);
        }
    }
    
    int size[Maxn], TG[Maxn][Maxn];
    int d[Maxn];
    
    int dp(int u)
    {
        int& ans = d[u];
        if(ans >= 0) return ans;
        ans = size[u];
        for(int v = 1; v <= scc_cnt; v++)
            if(u != v && TG[u][v]) 
                ans = max(ans, dp(v) + size[u]);
        return ans;
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            for(int i=0; i<n; i++)
                G[i].clear();
    
            for(int i=0; i<m; i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                u--;
                v--;
                G[u].push_back(v);
            }
    
            find_scc(n);
    
            memset(size,0,sizeof(size));
            memset(TG,0,sizeof(TG));
    
            for(int i=0; i<n; i++)
            {
                size[sccno[i]] ++;
                for(int j=0; j<G[i].size(); j++)
                {
                    TG[sccno[i]][sccno[G[i][j]]] = 1;
                }
            }
            int ans = 0;
            memset(d,-1,sizeof(d));
            for(int i=1; i<=scc_cnt; i++)
                ans = max(ans,dp(i));
    
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    js调试工具Console命令详解
    tomcat如何正确的开启远程调试功能
    Cleanup failed to process the following paths错误的解决
    MySQL查看SQL语句执行效率
    MYSQL 的静态表和动态表的区别, MYISAM 和 INNODB 的区别
    JAX-RS之queryparam、PathParam、DefaultValue、FormParam、Context、RestController等
    C语言中的printf函数的输入输出问题
    leetcode 21.Merge Two Sorted Lists ,java
    初识C++ 中的STL
    leetcode 58.Length of Last Word
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6078965.html
Copyright © 2011-2022 走看看