洛谷 - P1434 - 滑雪 - 有向图最长链

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\n",ans);

}

猜你喜欢

转载自www.cnblogs.com/Yinku/p/10659041.html