Tarjan 缩点
Posted water-radish
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tarjan 缩点相关的知识,希望对你有一定的参考价值。
//tarjan 缩点 //把强连通分量染成同样的颜色 用数组记录一下强连通分量内所有点权和 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; int n,m,cnt,ans,head[10001]; int t,sta[10001],vis[10001]; int dot,dfn[10001],low[10001]; int val[10001],a[200001],b[200001],ma[10001]; int tot,col[10001],sum[10001]; struct uio{ int to,next; }edge[200001]; void add(int x,int y) { edge[++cnt].next=head[x]; edge[cnt].to=y; head[x]=cnt; } void tarjan(int x) { dfn[x]=low[x]=++dot; sta[++t]=x; vis[x]=1; for(int i=head[x];i;i=edge[i].next) { int y=edge[i].to; if(!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); } else if(vis[y]) low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]) { tot++; while(sta[t+1]!=x) { col[sta[t]]=tot; sum[tot]+=val[sta[t]]; vis[sta[t]]=0; t--; } } } void get(int x) { if(ma[x]) return; ma[x]=sum[x]; int manum=0; for(int i=head[x];i;i=edge[i].next) { int y=edge[i].to; if(!ma[y]) get(y); manum=max(manum,ma[y]); } ma[x]+=manum; } int main() { 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[i],&b[i]); add(a[i],b[i]); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); memset(head,0,sizeof(head)); memset(edge,0,sizeof(edge)); cnt=0; for(int i=1;i<=m;i++) if(col[a[i]]!=col[b[i]]) add(col[a[i]],col[b[i]]); for(int i=1;i<=tot;i++) if(!ma[i]) { get(i); ans=max(ans,ma[i]); } printf("%d ",ans); return 0; }
以上是关于Tarjan 缩点的主要内容,如果未能解决你的问题,请参考以下文章
洛谷 P2194 HXY烧情侣Tarjan缩点 分析+题解代码