题目链接
定义dp[i]:走到顶点i的最长路径。
为了动态规划的无后效性,得先把边按权值排序。为了不让顶点之间的dp值重复计算,得把上一次的dp值保存下来。由于需要严格递增,所以权值相同的边用到的dp值是一样的,所以可以一次把所有权值相同的边一起加入图里,然后更新答案。
d
p
[
u
]
=
m
a
x
(
d
p
[
u
]
,
f
[
v
]
+
1
)
dp[u] = max(dp[u], f[v] + 1)
dp[u]=max(dp[u],f[v]+1)
d
p
[
v
]
=
m
a
x
(
d
p
[
v
]
,
f
[
u
]
+
1
)
dp[v] = max(dp[v], f[u] + 1)
dp[v]=max(dp[v],f[u]+1)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e4 + 10, inf = 0x3f3f3f3f, mod = 1e9 + 7;
struct e{
int u, v, c;
bool operator < (e b) {return c < b.c;}
}a[maxn];
int f[maxn], dp[maxn];
int main()
{
//ios::sync_with_stdio(0); cin.tie(0);
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int n, m, p = 0;
cin >> n >> m;
for (int i = 0; i < m; ++i){
cin >> a[i].u >> a[i].v >> a[i].c;
}
sort(a, a + m);
int i = 0, j = 1;
while (j < m){
while (j < m && a[j].c == a[i].c) ++j;
//为什么要一次把所有权值相同的边都一起处理呢?
//我们首先把权值相同的边的两个顶点原来的dp值都保存下来
//这些dp值都是没有加入新边的dp值,而加入的这些新边的权值一定都大于图里面的任何边
//为了保证新加的边一定会更新它的顶点的值,必须把权值相同的边一起加进来
//为了防止重复更新需要把上一次的值保存下来用上一次的值更新
for (int k = i; k < j; ++k) f[a[k].u] = dp[a[k].u], f[a[k].v] = dp[a[k].v];
for (int k = i; k < j; ++k) dp[a[k].u] = max(dp[a[k].u], f[a[k].v] + 1), dp[a[k].v] = max(dp[a[k].v], f[a[k].u] + 1);
i = j;
}
cout << *max_element(dp, dp + n) << endl;
//fclose(stdin);
//fclose(stdout);
return 0;
}