题目链接:http://codeforces.com/contest/459/problem/E
题意:给出m条边n个点每条边都有权值问如果两边能够相连的条件是边权值是严格递增的话,最长能接几条边。
题解:先按照边权排序一下,然后再利用dp求最值。
显然可以设dp[i]表示以i点为结尾最长能连几条边,dp[v]=dp[u]+1,u表示指向v的那个点,还有一点要注意的。
可能会遇到边权值相同的情况,这时候就不能这么转移了,所以在处理dp是要先处理一下边权相同的几个点。
for(int i = 0 ; i < m ;) {
int j = i;
for(j = i ; j < m && edge[i].w == edge[j].w ; j++) {
int u = edge[j].u;
int v = edge[j].v;
be[v] = max(be[v] , dp[u] + 1);
}
for(int k = i ; k < j ; k++) {
int v = edge[k].v;
dp[v] = max(dp[v] , be[v]);
}
i = j;
}
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int M = 3e5 + 10; struct Edge { int u , v , w; }edge[M]; bool cmp(Edge x , Edge y) { return x.w < y.w; } int dp[M] , num[M] , be[M]; int main() { int n , m; scanf("%d%d" , &n , &m); for(int i = 0 ; i < m ; i++) { scanf("%d%d%d" , &edge[i].u , &edge[i].v , &edge[i].w); } sort(edge , edge + m , cmp); memset(dp , 0 , sizeof(dp)); memset(be , 0 , sizeof(be)); for(int i = 0 ; i < m ;) { int j = i; for(j = i ; j < m && edge[i].w == edge[j].w ; j++) { int u = edge[j].u; int v = edge[j].v; be[v] = max(be[v] , dp[u] + 1); } for(int k = i ; k < j ; k++) { int v = edge[k].v; dp[v] = max(dp[v] , be[v]); } i = j; } int MAX = 0; for(int i = 1 ; i <= n ; i++) { MAX = max(MAX , dp[i]); } printf("%d " , MAX); return 0; }