https://www.luogu.org/problemnew/show/P1434
有向图的最长链怎么求?有环肯定不行,这里保证无环。(否则应该使用toposort先求出所有不带环的位置)
设dp[u]=以u点开始的最长链的长度,那么以u为子节点的v就有dp[v]=max(dp[v],dp[u]+1),遍历其每个子节点就可以得知其最长链。
所以最简单的方法其实是记忆化搜索。
第一次完全手写前向星版本的dfs。
#include<bits/stdc++.h> using namespace std; #define ll long long int g[105][105]; int head[10005]; struct Edge{ int v,nxt; Edge(int v=0,int nxt=0):v(v),nxt(nxt){} }edge[10005*4]; int indeg[10005]; int etop=0; void addedge(int u,int v){ edge[etop].v=v; edge[etop].nxt=head[u]; indeg[v]++; head[u]=etop++; } int n,m; int dp[10005]; int dfs(int id){ if(dp[id]!=-1) return dp[id]; else{ int res=0; for(int i=head[id];i!=-1;i=edge[i].nxt){ res=max(res,dfs(edge[i].v)); } res++; return dp[id]=res; } } int main(){ scanf("%d%d",&n,&m); memset(g,0x3f,sizeof(g)); memset(head,-1,sizeof(head)); memset(dp,-1,sizeof(dp)); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&g[i][j]); } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(g[i][j]>g[i-1][j]){ addedge((i-1)*m+j,(i-2)*m+j); } if(g[i][j]>g[i+1][j]){ addedge((i-1)*m+j,(i)*m+j); } if(g[i][j]>g[i][j-1]){ addedge((i-1)*m+j,(i-1)*m+j-1); } if(g[i][j]>g[i][j+1]){ addedge((i-1)*m+j,(i-1)*m+j+1); } } } int ans=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(indeg[(i-1)*m+j]==0){ ans=max(ans,dfs((i-1)*m+j)); } } } printf("%d ",ans); }