zoukankan      html  css  js  c++  java
  • uva 11324 The Largest Clique 强连通分量求缩点构造DAG

    题目:uva 11324 The Largest Clique
    从图中某点出发,求最远能够一次走过多少个节点

    分析:
    tarjan求gcc,然后构造出新图,新图是一个dag,对于dag上用dp求出最长路径即可。dp转移方程为dp[x] = size[x] + max(dp[y]); 缩点后有边x到y的边,记忆化搜索就行了,具体看实现代码

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    
    using namespace std;
    
    const int maxn = 1005;
    const int maxm = 50005;
    
    #define debug puts("here");
    
    int dfn[maxn],low[maxn],stack[maxn],father[maxn],bcnt,top,depth;
    bool instack[maxn];
    int po[maxn],tol,n,m;
    int id[maxn];
    int dp[maxn];
    int sum[maxn];
    
    vector<int> vec[maxn];
    
    struct node{
        int y,next;
    }edge[maxm];
    
    void add(int x,int y){
        edge[++tol].y = y;
        edge[tol].next = po[x];
        po[x] = tol;
    }
    
    void dfs(int x){	//递归实现tarjan算法
        low[x] = dfn[x] = ++depth;
        instack[x] = true;
        stack[++top] = x;
        int y;
        for(int i=po[x];i;i=edge[i].next){
            y = edge[i].y;
            if(!dfn[y]){
                dfs(y);
                low[x] = min(low[x],low[y]);
            }
            else if(instack[y])
                low[x] = min(low[x],dfn[y]);
        }
        if(low[x]==dfn[x]){
            ++bcnt;
            do{
                y = stack[top--];
                instack[y] = false;
                father[y] = bcnt;
            }while(x!=y);
        }
    }
    
    void tarjan(){
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        top = bcnt = depth = 0;
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                dfs(i);
    }
    
    int f(int x){	//记忆化方法求dag上的最长路径
        if(dp[x])
            return dp[x];
        int ans = 0;
        for(int i=0;i<(int)vec[x].size();i++){	//从x的所有边出发,求出最大的路径
            int y = vec[x][i];
            ans = max(ans,f(y));	//转移方程
        }
        dp[x] = ans+sum[x];
        return dp[x];
    }
    
    void dag(){
        memset(id,0,sizeof(id));
        memset(sum,0,sizeof(sum));
        memset(dp,0,sizeof(dp));
    
        for(int i=1;i<=n;i++)
            vec[i].clear();
    
        for(int x=1;x<=n;x++){		//构造新图
            for(int j=po[x];j;j=edge[j].next){
                int y = edge[j].y;
                if(father[x]!=father[y]){
                    vec[father[x]].push_back(father[y]);
                    id[father[y]] ++;
                }
            }
            sum[father[x]] ++;	//统计每个缩点后的该节点所包含的所有原图的节点数目
        }
    
        int ans = 0;
        for(int i=1;i<=bcnt;i++)
            if(!id[i])
                ans = max(f(i),ans);
        cout<<ans<<endl;
    }
    
    int main(){
        freopen("sum.in","r",stdin);
        int ncase;
        cin>>ncase;
        while(ncase--){
            cin>>n>>m;
            int x,y;
            memset(po,0,sizeof(po));
            tol = 0;
            while(m--){
                scanf("%d%d",&x,&y);
                add(x,y);
            }
            tarjan();
            dag();
        }
        return 0;
    }
    

      

  • 相关阅读:
    数据库索引的作用和长处缺点
    ping不通的几种可能原因
    UVA
    strtok、strtok_s、strtok_r 字符串切割函数
    CheckBoxPreference组件
    EM算法原理
    Android中ExpandableListView控件基本使用
    拓扑排序的原理及事实上现
    DropdownList绑定的两种方法
    leetcode第一刷_Length of Last Word
  • 原文地址:https://www.cnblogs.com/yejinru/p/2755616.html
Copyright © 2011-2022 走看看