DAG的运用:拓扑排序(AOV),关键路径(AOE)与dp的关系

dp在DAG中有两个运用,一个是固定终点和起点的最长路(最短路)

其中最长路的算法就是关键路径(AOE)的算法。

下面是代码

#include<cstdio>
#include<algorithm>
#define maxn 2001
using namespace std;
int a[10],head[maxn],n,p,f[maxn],tp[maxn],de[maxn],ds[maxn];
struct ss
{
    int to,w,last;
}x[maxn*1000];
void add(int a,int b,int c)
{
    x[++p].to=b;
    x[p].last=head[a];
    x[p].w=c;
    head[a]=p;
}
int dp(int a)
{
    if(f[a]!=0) return f[a];
    if(!de[a]) return 0;
    int v=head[a],t=0;
    while(v)
    {
        if(dp(x[v].to)+x[v].w>t)
            {
             t=dp(x[v].to)+x[v].w;
             ds[a]=x[v].to;
            }
        v=x[v].last;
    }
    f[a]=t;
    return f[a];
}
void out(int a)
{
    if(!a) return;
    out(ds[a]);
    printf("%d ",a);
}
int main()
{
    scanf("%d",&n);
    int a1,a2,a3;
    while(scanf("%d%d%d",&a1,&a2,&a3)==3)
    {
        add(a2,a1,a3);
        de[a2]++;
    }
    int ans=0,ansv;
    for(int i=1;i<=n;i++)
        if(dp(i)>ans)
         {
          ans=dp(i);
          ansv=i;
         }
    printf("%d
",ans);    
    out(ansv);
    return 0;
}
 

关于拓扑排序(AOV)有两个算法,一个是dfs,运用搜索树的性质,其一个点的子节点输出完后,再输出父节点。

还有就是广搜算法

下面给出代码

dfs

#include<cstdio>
#define N 2000+10
using namespace std;
int head[N],num;
struct edge{
    int next,to;
}e[N*(N-1)];
int dfn[N][2],degree[N],ok=1,index,tot=0,topu[N];
void add(int from,int to)
{
    e[++num].next=head[from];
    e[num].to=to;
    head[from]=num;
}
void dfs(int u)
{
    if(!ok)return;
    dfn[u][0]=++index;
    for(int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(dfn[v][0]&&!dfn[v][1]){ok=0;return;}
        else if(!dfn[v][0]){
            dfs(v);
        }
    }
    dfn[u][1]=++index;
    topu[tot--]=u;
}
int main()
{
    int n;
    scanf("%d",&n);
    int x,y;
    while(scanf("%d%d",&x,&y)==2){add(x,y);degree[y]++;}
    int flag=0;
    for(int i=1;i<=n;i++)
    {
        if(degree[i]==0){x=i,flag=1;}
    }
    if(!flag){printf("NO");return 0;}
    tot=n;
    for(int i=1;i<=n;i++)
    {
        if(!ok)break;
        if(!dfn[i][0]/*&&degree[i]==0*/)dfs(i);
    }
    if(ok==0){printf("NO");return 0;}
    for(int i=1;i<=n;i++)printf("%d ",topu[i]);
    return 0;
}

bfs

#include<cstdio>
#include<algorithm>
using namespace std;
int n,a,b,head[2001],num,z[2001],top,cl,op,deg[2001];
struct ss
{
    int last,to;
}e[2000000];
void add(int a,int b)
{
    e[++num].last=head[a];
    e[num].to=b;
    head[a]=num;
}
void bfs()
{
    cl=1;
    while(cl<=top)
    {
        int m=z[cl],t=head[m];
        while(t)
        {
            deg[e[t].to]-=1;
            if(deg[e[t].to]==0)
                z[++top]=e[t].to;
            t=e[t].last;
        }
        cl+=1;
    }
}
int main()
{
    scanf("%d",&n);
    while(scanf("%d%d",&a,&b)==2)
    {
        add(a,b);
        deg[b]++;
    }
    for(int i=1;i<=n;i++)
    if(deg[i]==0)z[++top]=i;
    bfs();
    if(top<n)printf("NO");
    else
    for(int i=1;i<=top;i++)
    printf("%d ",z[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/star-eternal/p/7607666.html