zoukankan      html  css  js  c++  java
  • UVA 11324 The Largest Clique (强连通分量,dp)

    给出一个有向图,求一个最大的结点集合,任意两个点u,v。u可到达v或v可到达u。

    一个强连通分量肯定一起选的。而且只能在一条路径上。

    所以先找出所有scc,然后缩点找一条最大权的路径,按拓扑序跑DAG上的dp。

    注意0,0这组数据

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1005,maxm = 5e5+1;
    
    int head[maxn],to[maxm],nxt[maxm];
    
    void addEdge(int u,int v,int i)
    {
        to[i] = v;
        nxt[i] = head[u];
        head[u] = i;
    }
    
    int pre[maxn],low[maxn],sccno[maxn],dfs_clock,scc_cnt;
    stack<int> stk;
    
    void tarjan(int u)
    {
        pre[u] = low[u] = ++dfs_clock;
        stk.push(u);
        for(int i = head[u]; ~i; i = nxt[i]){
            int v = to[i];
            if(!pre[v]){
                tarjan(v);
                low[u] = min(low[u],low[v]);
            }else if(!sccno[v]){
                low[u] = min(low[u],pre[v]);
            }
        }
        if(pre[u] == low[u]){
            scc_cnt++;
            while(stk.size()){
                int x = stk.top(); stk.pop();
                sccno[x] = scc_cnt;
                if(x == u) break;
            }
        }
    }
    
    void find_scc(int n)
    {
        memset(pre,0,sizeof(pre));
        memset(sccno,0,sizeof(sccno));
        dfs_clock = scc_cnt = 0;
        for(int i = 0; i < n; i++){
            if(!pre[i]) tarjan(i);
        }
    }
    
    vector<int> G[maxn];
    int wei[maxn], deg[maxn];
    
    void buildDAG(int n)
    {
        for(int i = 1; i <= scc_cnt; i++) G[i].clear(),deg[i] = wei[i] = 0;
        for(int u = 0; u < n; u++){
            int v0 = sccno[u]; wei[v0]++;
            for(int i = head[u]; ~i; i = nxt[i]){
                int v1 = sccno[to[i]];
                if(v0 != v1) G[v0].push_back(v1),deg[v1]++;
            }
        }
    }
    
    int dp[maxn];
    int topo()
    {
        memset(dp,-1,sizeof(dp));
        queue<int> q;
        for(int i = 1; i <= scc_cnt; i++){
            if(!deg[i]) q.push(i),dp[i] = wei[i];
        }
        while(q.size()){
            int u = q.front(); q.pop();
            for(int i = 0; i < (int)G[u].size(); i++){
                int v = G[u][i];
                dp[v] = max(dp[v],dp[u]+wei[v]);
                if(--deg[v] == 0) q.push(v);
            }
        }
        int ans = 0;
        for(int i = 1; i <= scc_cnt; i++){
            ans = max(dp[i],ans);
        }
        return ans;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T; scanf("%d",&T);
        while(T--){
            int n,m;
            memset(head,-1,sizeof(head));
            scanf("%d%d",&n,&m);
            for(int i = 0; i < m; i++){
                int u,v; scanf("%d%d",&u,&v);
                addEdge(u-1,v-1,i);
            }
            find_scc(n);
            buildDAG(n);
            printf("%d
    ",topo());
        }
        return 0;
    }
  • 相关阅读:
    pureftpd无法上传、新建、覆盖文件的解决方法
    nginx 安装
    Generating Artifacts问题解决汇总
    Java Project和Web Project 区别
    CString 截取字符串全攻略
    截取字符串--sql和access的区别
    VC++线程函数内怎么调用外部函数
    CTime与CString相互转化
    CString的所有函数
    深层次的理解_variant_t
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4777275.html
Copyright © 2011-2022 走看看