Tarjan求强联通分量
hihocoder1185
题意
分析
SCC后剩下的缩点都是scc[i]=i,若最后剩下n个点,并不一定是1~n
第一种:拓扑排序,对每一个点以其为终点的最大值
第二种:dfs记忆化搜索,对每一个点以其为起点的最大值
显然第二种更简单易写
dfs记忆化搜索
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; const int INF = 0x3f3f3f3f; stack<int>s; bool vis[maxn]; int dfn[maxn],low[maxn],scc[maxn],idx; vector<int>g[maxn],newp[maxn]; int n,m,u,v,w[maxn],answer[maxn]; void tarjan(int u) { dfn[u]=low[u]=++idx; s.push(u); vis[u]=true; int v; for(int i=0;i<g[u].size();++i){ v=g[u][i]; if(dfn[v]==0){ tarjan(v); low[u]=min(low[u],low[v]); }else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) do{ v=s.top(); s.pop(); scc[v]=u;//指向根节点 vis[v]=false; }while(u!=v); } void suodian() { for(int i=1;i<=n;i++) { int len=g[i].size(); for(int j=0;j<len;j++) { int to=g[i][j]; if(scc[i]==to||w[to]==0) continue; if(scc[to]!=to) w[scc[to]]+=w[to],w[to]=0; else newp[scc[i]].push_back(to); } } } int d[maxn]; int ans; int dfs(int x) { if(answer[x]) { //cout<<answer[x]<<endl; return answer[x]; } int len=newp[x].size(); if(len==0) return answer[x]=w[x]; for(int i=0;i<len;i++) { int to=newp[x][i]; int t=dfs(to); answer[x]=max(answer[x],w[x]+answer[to]); } } int main() { ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=n;i++) cin>>w[i]; for(int i=1;i<=m;i++) { cin>>u>>v; g[u].push_back(v); } for(int i=1;i<=n;i++) scc[i]=i; tarjan(1); suodian(); memset(vis,false,sizeof(vis)); dfs(scc[1]); printf("%d\n",answer[scc[1]]); return 0; }
拓扑排序
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; const int INF = 0x3f3f3f3f; stack<int>s; bool vis[maxn]; int dfn[maxn],low[maxn],scc[maxn],idx; vector<int>g[maxn],newp[maxn]; int n,m,u,v,w[maxn],answer[maxn]; void tarjan(int u) { dfn[u]=low[u]=++idx; s.push(u); vis[u]=true; int v; for(int i=0;i<g[u].size();++i){ v=g[u][i]; if(dfn[v]==0){ tarjan(v); low[u]=min(low[u],low[v]); }else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) do{ v=s.top(); s.pop(); scc[v]=u;//指向根节点 vis[v]=false; }while(u!=v); } void suodian() { for(int i=1;i<=n;i++) { int len=g[i].size(); for(int j=0;j<len;j++) { int to=g[i][j]; if(scc[i]==to||w[to]==0) continue; if(scc[to]!=to) w[scc[to]]+=w[to],w[to]=0; else newp[scc[i]].push_back(to); } } } int d[maxn]; void dfs(int x) { vis[x]=1; int len=newp[x].size(); for(int i=0;i<len;i++) { int to=newp[x][i]; d[to]++; if(!vis[to]) dfs(to); } } queue<int>q; int ans; void tpsort(int x) { q.push(x); answer[x]=w[x]; while(!q.empty()) { //cout<<123<<endl; int now=q.front(); q.pop(); ans=max(ans,answer[now]); int len=newp[now].size(); for(int i=0;i<len;i++) { int to=newp[now][i]; // cout<<to<<' '<<scc[to]<<endl; answer[to]=max(answer[to],w[to]+answer[now]); /// d[to]--; if(d[to]==0) q.push(to); } } } int main() { ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=n;i++) cin>>w[i]; for(int i=1;i<=m;i++) { cin>>u>>v; g[u].push_back(v); } for(int i=1;i<=n;i++) scc[i]=i; tarjan(1); suodian(); memset(vis,false,sizeof(vis)); dfs(scc[1]); tpsort(scc[1]); printf("%d\n",ans); return 0; }
要么优秀要么生锈