luogu P3387 模板缩点_拓扑排序

Posted guangheli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P3387 模板缩点_拓扑排序相关的知识,希望对你有一定的参考价值。

Code:

#include <stack>
#include <cstdio>
#include <algorithm>
#include <queue> 
#include <cstring>
#include <map> 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;
namespace Tarjan{
    #define maxn 1000000 
    #define ll long long 
    map<int,int>ed[maxn]; 
    int scc,sig; 
    int vis[maxn]; 
    int du[maxn]; 
    int idx[maxn];   
    int pre[maxn],low[maxn]; 
    int val[maxn];       
    long long value[maxn];  
    long long ans[maxn]; 
    stack<int>S; 
    queue<int>Q; 
    struct graph{
        int cnt; 
        int head[maxn],to[maxn<<1],nex[maxn<<1];  
        void addedge(int u,int v){
            nex[++cnt] = head[u],head[u]=cnt,to[cnt] = v; 
        }
    }G1,G2; 
    void tarjan(int u){
        S.push(u); 
        vis[u] = 1;         
        pre[u] = low[u] = ++scc; 
        for(int v=G1.head[u];v;v=G1.nex[v]){
            if(!vis[G1.to[v]]) {
                tarjan(G1.to[v]); 
                low[u] = min(low[u],low[G1.to[v]]); 
            }
            else if(vis[G1.to[v]] == 1) low[u] = min(low[u],pre[G1.to[v]]); 
        }
        if(pre[u] == low[u]) {
            ++sig; 
            for(;;){
                int a=S.top(); S.pop(); 
                vis[a] = -1,idx[a] = sig; 
                value[sig] += (ll)val[a]; 
                if(a==u) break;     
            }
        }     
    }   
    void toposort(){
        for(int i=1;i<=sig;++i) 
            for(int j=G2.head[i];j;j=G2.nex[j])   ++du[G2.to[j]]; 
        for(int i=1;i<=sig;++i) if(du[i]==0) Q.push(i),ans[i] = value[i]; 
        while(!Q.empty()){
            int u=Q.front(); Q.pop(); 
            for(int v=G2.head[u];v;v=G2.nex[v]){ 
                ans[G2.to[v]] = max(ans[G2.to[v]],ans[u] + value[G2.to[v]]); 
                --du[G2.to[v]]; 
                if(du[G2.to[v]]==0) Q.push(G2.to[v]); 
            }
        }
        long long fin=0; 
        for(int i=1;i<=sig;++i) 
            fin=max(fin,ans[i]); 
        printf("%lld",fin); 
    }
    int main(){
        int n,m,a,b; 
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%d",&val[i]);     
        for(int i=1;i<=m;++i) {   
            scanf("%d%d",&a,&b);      
            G1.addedge(a,b); 
        }
        for(int i=1;i<=n;++i) if(!vis[i]) tarjan(i);                       
        for(int i=1;i<=n;++i) 
            for(int v=G1.head[i];v;v=G1.nex[v])
                if(idx[i]!=idx[G1.to[v]] && !ed[idx[i]][idx[G1.to[v]]])  
                    G2.addedge(idx[i],idx[G1.to[v]]),ed[idx[i]][idx[G1.to[v]]]=1;    
        toposort(); 
        return 0; 
    }
}; 
int main(){
    Tarjan::main(); 
    return 0; 
}

  

以上是关于luogu P3387 模板缩点_拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章

P3387 模板缩点 [强连通分量][DAG]

Luogu P3387 模板缩点

P3387 模板缩点

洛谷 P3387 模板缩点 题解

P3387 模板缩点

洛谷 P3387 模板缩点