【CF459E】Pashmak and Graph(递推+动规)

https://www.luogu.org/problem/CF459E

f[i]表示以边i结尾的最长路径,g[i]表示以点i结尾的最长路径,f[i]=g[e[i].u]+1。注意特判边权相等的情况,每次更新边连接的出度点的g即可。

推的话,数据范围3e5所以想到dp,而且必须是一维,固定一维枚举一维。所以边权排个序,枚举时就不用管边权递增的约束条件,只需要特判下相等的情况。状态和动态转移方程还是比较神仙(对我这种蒟蒻来说),拿结尾边和点做状态,学到就是赚到。

#include<bits/stdc++.h>
#define ri register int
#define ll long long
#define For(i,l,r) for(ri i=l;i<=r;i++)
#define Dfor(i,r,l) for(ri i=r;i>=l;i--)
using namespace std;
const int M=300005;
int n,m,cnt,f[M],g[M],t=1,ans;
struct node{
    int u,to,w;
    bool operator <(const node&x)const{
        return w<x.w;
    }
}e[M];
inline ll read(){
    ll f=1,sum=0;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
    return f*sum;
}
inline bool cmp(node x,node y){return x.w<y.w;}
int main(){
    n=read(),m=read();
    For(i,1,m){
        e[i].u=read(),e[i].to=read(),e[i].w=read();
    }
    sort(e+1,e+m+1,cmp);
    For(i,1,m){
        f[i]=g[e[i].u]+1;
        if(e[i].w!=e[i+1].w){
            For(j,t,i){
                g[e[j].to]=max(g[e[j].to],f[j]);//当前的下一个点是由连接它的边推来的    
            }
            t=i+1;
        }
    }
    For(i,1,m) ans=max(ans,f[i]);
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/jian-song/p/11768212.html