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.要好好处理后效性

posted @ 2016-10-16 21:21  xgtao  阅读(299)  评论(0编辑  收藏  举报