tarjan算法与拓扑排序
Posted wangqianyv
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tarjan算法与拓扑排序相关的知识,希望对你有一定的参考价值。
算法介绍
tarjan
tarjan算法要求使有向图。
Tarjan就是一个辅助作用,把有环图缩为无环图,也就是将强联通分量缩成一个点。
几个数组 dfn时间戳,low仍在栈中的最小时间戳,dag缩点后的数组,ins是否在栈中。
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
ins[x]=1;
st.push(x);
for(int i=0;i<g[x].size();i++)
{
int q=g[x][i];
if(dfn[q]==0)
{
tarjan(q);
low[x]=min(low[x],low[q]);
}
else if(ins[q]==1)
{
low[x]=min(low[x],dfn[q]);
}
}
if(dfn[x]==low[x])
{
numb++;
int q;
do
{
q=st.top();
st.pop();
ins[q]=0;
dag[q]=numb;
num[numb]++;
p[numb]+=a[q];
}
while(q!=x);
}
}
拓扑排序
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
拓扑排序步骤
统计入度,入度为0入栈,递推并更新入度,入度为0入栈,栈空结束
queue<int>q;
int tot=0;
for(int i=1;i<=numb;i++)
{
if(!ind[i])
{
q.push(i);
dist[i]=p[i];
}
}
while(!q.empty())
{
int k=q.front();q.pop();
for(int i=0;i<g1[k].size();i++)
{
int v=g1[k][i];
dist[v]=max(dist[v],dist[k]+p[v]);
ind[v]--;
if(ind[v]==0)q.push(v);
}
}
例题
代码
const int maxn=100015;
int numb,cnt;
int dist[maxn];
int dag[maxn],num[maxn];
int a[maxn];
int ind[maxn];
stack<int>st;
int p[maxn],dfn[maxn],ins[100015],low[100015];
vector<int>g[maxn],g1[maxn];
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
ins[x]=1;
st.push(x);
for(int i=0;i<g[x].size();i++)
{
int q=g[x][i];
if(dfn[q]==0)
{
tarjan(q);
low[x]=min(low[x],low[q]);
}
else if(ins[q]==1)
{
low[x]=min(low[x],dfn[q]);
}
}
if(dfn[x]==low[x])
{
numb++;
int q;
do
{
q=st.top();
st.pop();
ins[q]=0;
dag[q]=numb;
num[numb]++;
p[numb]+=a[q];
}
while(q!=x);
}
}
main(void)
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
g[u].push_back(v);
}
for(int i=1;i<=n;i++)
{
if(!dag[i])
tarjan(i);
}
for(int i=1;i<=n;i++)
for(int j=0;j<g[i].size();j++)
{
int u=dag[i],v=dag[g[i][j]];
if(u!=v)
{
g1[u].push_back(v);
ind[v]++;
}
}
queue<int>q;
int tot=0;
for(int i=1;i<=numb;i++)
{
if(!ind[i])
{
q.push(i);
dist[i]=p[i];
}
}
while(!q.empty())
{
int k=q.front();q.pop();
for(int i=0;i<g1[k].size();i++)
{
int v=g1[k][i];
dist[v]=max(dist[v],dist[k]+p[v]);
ind[v]--;
if(ind[v]==0)q.push(v);
}
}
int ans=0;
for(int i=1;i<=numb;i++)
ans=max(ans,dist[i]);
cout<<ans;
}
以上是关于tarjan算法与拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章