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\n",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]/*&°ree[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; }
夫君子之行,
静以修身,俭以养德;
非澹泊无以明志,
非宁静无以致远。
夫学须静也,才须学也;
非学无以广才,非志无以成学。
慆慢则不能励精,
险躁则不能冶性。
年与时驰,意与日去,
遂成枯落,多不接世。
悲守穷庐,将复何及!