HNU 1447 最长上升路径
题意:
给出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.要好好处理后效性