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 模板缩点_拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章