求入度为0的点到出度为0的点的最长路
题目中已经说明了没有环,所以是DAG图,可以拓扑排序+DP解决,复杂度为O(E)
一开始想DFS的,TLE,究其原因,图中的交叉链可能比较多,导致有些边被多次重复搜索
另外,进行拓扑排序时,只有当一个点的入度减为0时才会将它入队列,也就是说当它的前驱节点都访问过以后才会访问它,这也保证了可以用DP解决
代码:
#include<iostream> #include<cstdio> #include<memory.h> #include<queue> using namespace std; const int MAX=100005; const int inf=1<<30; struct node { int v,next; }g[MAX*20]; int e,n,m; int adj[MAX],ind[MAX],out[MAX],val[MAX],dp[MAX]; void topsort() { queue<int>que; int i,j,u,v; for(i=1;i<=n;i++) { if(ind[i]==0) { que.push(i); dp[i]=val[i]; } } while(!que.empty()) { u=que.front(); que.pop(); for(i=adj[u];i!=-1;i=g[i].next) { v=g[i].v; if(dp[v]<dp[u]+val[v]) { dp[v]=dp[u]+val[v]; } if(--ind[v]==0) que.push(v); } } } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF) { e=0; memset(adj,-1,sizeof(adj)); memset(ind,0,sizeof(ind)); memset(out,0,sizeof(out)); for(i=1;i<=n;i++) { dp[i]=-inf; scanf("%d",&val[i]); } while(m--) { scanf("%d%d",&i,&j); out[i]++; ind[j]++; g[e].v=j; g[e].next=adj[i]; adj[i]=e++; } topsort(); int ans=-inf; for(i=1;i<=n;i++) { if(out[i]==0&&dp[i]>ans) ans=dp[i]; } cout<<ans<<endl; } return 0; }