• 图论--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;
    }
  • 相关阅读:
    POJ2406【KMP-next数组】
    POJ2752【KMP-next数组含义】
    POJ3696【欧拉函数+欧拉定理】
    POJ3692【二分匹配】
    POJ3697【BFS】
    CodeForces599D【数学】
    CodeForces599C【贪心】
    HDU1829【种类并查集】
    HDU3038【种类并查集】
    POJ1182【种类并查集】
  • 原文地址:https://www.cnblogs.com/stone41123/p/7581268.html
Copyright © 2020-2023  润新知