zoukankan      html  css  js  c++  java
  • 图论--tarjan缩点

    模板:洛谷P3387
    关于tarjan大神的算法我也只能抄抄代码了(滑稽)
    其实《算法竞赛入门经典:训练指南》里有讲解,很详细。
    代码:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    vector<int> G[10001];
    int n,m;
    int dfn_clock;
    int v[10001];
    int head[10001];
    int dfn[10001];
    int low[10001];
    int vis[10001];
    stack<int> s;
    int sccnum[10001];
    int scccnt;
    vector<int> S[10001];
    int V[10001];
    int in[10001];
    void tarjan(int x){
        dfn[x]=low[x]=++dfn_clock;
        vis[x]=1;
        in[x]=1;
        s.push(x);
        for(int i=0;i<G[x].size();i++){
            int u=G[x][i];
            if(!vis[u]){
                tarjan(u);
                low[x]=min(low[x],low[u]);
            }
            else if(in[u]){
                low[x]=min(low[x],dfn[u]);
            }
        }
        if(dfn[x]==low[x]){
            scccnt++;
            while(s.top()!=x){
                sccnum[s.top()]=scccnt;
                V[scccnt]+=v[s.top()];
                in[s.top()]=0;
                s.pop();
            }
            sccnum[x]=scccnt;
            V[scccnt]+=v[x];
            in[x]=0;
            s.pop();
        }
    }
    int f[10001];
    int dp(int x){
        if(f[x]){
            return f[x];
        }
        f[x]=V[x];
        int mx=0;
        for(int i=0;i<S[x].size();i++){
            int u=S[x][i];
            mx=max(mx,dp(u));
        }
        f[x]+=mx;
        return f[x];
    }
    int main(){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&v[i]);
        }
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d %d",&x,&y);
            G[x].push_back(y);
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                tarjan(i);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=0;j<G[i].size();j++){
                int u=G[i][j];
                if(sccnum[i]!=sccnum[u]){
                    S[sccnum[i]].push_back(sccnum[u]);
                }
            }
        }
        int ans=0;
        for(int i=1;i<=scccnt;i++){
            if(!f[i]){
                ans=max(ans,dp(i));
            }
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Java异常处理机制(转)
    深入探讨 java.lang.ref 包(转)
    一篇不错的讲解Java异常的文章
    Java国际化学习(一)介绍
    Java泛型集合排序(转)
    Java常见异常总结 (转)
    java中的异常处理机制
    深入分析 Java I/O 的工作机制(转)
    java里BufferedReader和Scanner
    JS深入学习知识整理
  • 原文地址:https://www.cnblogs.com/stone41123/p/7581268.html
Copyright © 2011-2022 走看看