CF960F Pathwalks
第一眼看去很容易想到 LIS 问题,从而想到 DP 去解决这道题。
这个题和 LIS 的区别就是状态转移时还要保证两个点在原图中有边,而且以一个点可以由多个边转移过来,所以我们状态转移方程里要加上一维表示最后的边权。
定义
对于一条有向边
如果直接暴力转移的话,我们要暴力枚举
我们并不需要要枚举
我们可以对每个点用 map 维护。
首先在
同时我们要维护
通过维护双单调性,我们也保证了第一步的正确性,同样这么用 map 还有UVA12161,都运用到了 map 第一关键字的自动排序。
代码:
#include<cstdio>
#include<map>
#include<cstring>
#define rep(x,y,z) for(int x=y;x<=z;x++)
using namespace std;
const int N=1e5+10;
map<int,int>dp[N];
int find(int u,int x)
{
auto it=dp[u].lower_bound(x);
return it==dp[u].begin()?0:(--it)->second;
}
int main()
{
int n,m,ans=0;
scanf("%d%d",&n,&m);
rep(i,1,m)
{
int u,v,k;
scanf("%d%d%d",&u,&v,&k);
int res=find(u,k)+1;
if(res>find(v,k))
{
auto it=dp[v].lower_bound(k);
dp[v][k]=res;
while(it!=dp[v].end()&&it->second<=res) dp[v].erase(it++);
}
ans=max(ans,res);
}
printf("%d",ans);
return 0;
}