题意:
给出n( <= 3e5)个点,m(<= 3e5)条带权的有向边,求权值上升的最长路径的长度。
题解:
1.因为求的是最长上升的路径,考虑动态规划,定义状态dp[u] 表示以u结尾上升路径最长长度。
2.为了排除后效性那么首先对所有边从小到大排序,dp[v] = max (dp[v], dp[u] + 1)
3.转移的条件dp[v] < dp[u] + 1因为这样保证了路径的递增,所以不能立即更新,需要把要更新的边都存下来一起更新~
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 4e5 + 7;
int dp[N], n, m;
struct edge{
int u, v, w;
bool operator < (const edge &X) const{return w < X.w;}
} e[N];
struct node{int v, len;} K[N];
int main(){
scanf("%d%d", &n , &m);
for (int i = 1; i <= m; ++i) {
int u, v, w;
scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
}
sort(e+1, e+m+1);
int pre = 0;
for (int i = 1; i <= m; ++i) {
if (e[i].w == e[i + 1].w && i != m) continue;
int cnt = 0;
for (int j = pre + 1; j <= i; ++j)
if (dp[e[j].u] + 1 > dp[e[j].v])
K[++cnt] = (node){e[j].v, dp[e[j].u] + 1};
for(int j = 1;j <= cnt;++j)
dp[K[j].v] = max(dp[K[j].v],K[j].len);
pre = i;
}
int ans = 0;
for (int i = 1; i <= n; ++i) ans = max (ans, dp[i]);
printf("%d\n", ans);
return 0;
}
总结:
1.要好好处理后效性