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; }