zoukankan      html  css  js  c++  java
  • uva11324 有向图的强连通分量+记忆化dp

    给一张有向图G, 求一个结点数最大的结点集,使得该结点集中任意两个结点u和v满足,要么u可以到达v, 要么v可以到达u(u和v相互可达也可以)。

    因为整张图可能存在环路,所以不好使用dp直接做,先采用有向图的强连通分量,进行缩点,然后得到一个有向无环图(DAG) 在采用记忆话dp 去做即可

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <string.h>
    #include <vector>
    #include <stack>
    using namespace std;
    const int maxn = 1000+10;
    vector<int>G[maxn];
    int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
    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 n){
         dfs_clock =scc_cnt =0;
         memset(sccno,0,sizeof(sccno));
         memset(pre, 0, sizeof(pre));
         while(!S.empty())S.pop();
         for(int i=0; i<n; ++i)
            if(!pre[i]) dfs(i);
    }
    int value[maxn],dp[maxn];
    vector<int> E[maxn];
    int dff(int u){
        if(dp[u]!=-1) return dp[u];
         dp[u]=0;
        for(int i=0; i<E[u].size(); ++i){
             int v = E[u][i];
             dp[u]=max(dff(v),dp[u]);
        }
        dp[u]+=value[u];
        return dp[u];
    }
    int main()
    {
         int cas;
         scanf("%d",&cas);
         for(int cc =1; cc<=cas; ++cc){
    
               int n,m;
               scanf("%d%d",&n,&m);
               for(int i=0; i<=n; ++i)
                G[i].clear(),E[i].clear();
               for(int i=1; i<=m; ++i){
                   int u,v;
                   scanf("%d%d",&u,&v);
                   u--; v--;
                   G[u].push_back(v);
               }
               find_scc(n);
               memset(value,0,sizeof(value));
               for(int u=0; u<n; ++u){
                    value[sccno[u]]++;
                    for(int j=0; j<G[u].size(); ++j){
                         int v=G[u][j];
                         if(sccno[u]!=sccno[v]){
                              E[sccno[u]].push_back(sccno[v]);
                         }
                    }
               }
               memset(dp , -1 , sizeof(dp));
               int ans=0;
               for(int i=1; i <= scc_cnt; ++i){
                    if(dp[i]==-1)
                     dff(i);
                     ans=max(ans,dp[i]);
               }
               printf("%d
    ",ans);
         }
        return 0;
    }
    View Code
  • 相关阅读:
    CSS之定位
    选择器小结
    ASP.NET Web API + Elasticsearch 6.x 快速做个全文搜索
    获取服务端https证书
    使用 JSON JavaScriptSerializer 进行序列化或反序列化时出错
    MVC和WebForm的优缺点比较
    C#之VS开发工具快捷键大全
    Scrum敏捷开发之扫盲篇
    Asp.net 中数据量较小插入数据库
    xml解析
  • 原文地址:https://www.cnblogs.com/Opaser/p/4318674.html
Copyright © 2011-2022 走看看