题目链接:http://codeforces.com/problemset/problem/459/E
题意:
给你一个有向图,每条边有边权。
让你找出一条路径,使得这条路径上的边权严格递增。
问你这样的路径最长有多长。
题解:
先将所有边按边权从小到大排序,以保证边权递增。
表示状态:
dp[i] = max len
表示以点i为终点时的最长路径长度。
找出答案:
ans = max dp[i]
如何转移:
枚举每条边e[i],则有:
dp[e[i].t] = max(dp[e[i].t], dp[e[i].s]+1)
但是要注意,当枚举一些边的边权相同时,直接更新dp[e[i].t]是不行的。
比如一条链上的边权均相同的情况。
所以当边权相同时,先暂时将新的dp[e[i].t]存到f数组中,等这些边权相同的边枚举完之后,再用f数组更新dp。
边界条件:
set dp & f = 0
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <vector> 6 #define MAX_N 300005 7 8 using namespace std; 9 10 struct Edge 11 { 12 int s; 13 int t; 14 int len; 15 Edge(int _s,int _t,int _len) 16 { 17 s=_s; 18 t=_t; 19 len=_len; 20 } 21 Edge(){} 22 friend bool operator < (const Edge &a,const Edge &b) 23 { 24 return a.len<b.len; 25 } 26 }; 27 28 int n,m; 29 int ans=0; 30 int f[MAX_N]; 31 int dp[MAX_N]; 32 Edge edge[MAX_N]; 33 34 void read() 35 { 36 scanf("%d%d",&n,&m); 37 int a,b,v; 38 for(int i=0;i<m;i++) 39 { 40 scanf("%d%d%d",&a,&b,&v); 41 edge[i]=Edge(a,b,v); 42 } 43 } 44 45 void work() 46 { 47 sort(edge,edge+m); 48 memset(dp,0,sizeof(dp)); 49 memset(f,0,sizeof(f)); 50 int pos=0; 51 for(int i=0;i<m;i++) 52 { 53 Edge temp=edge[i]; 54 f[temp.t]=max(f[temp.t],dp[temp.s]+1); 55 ans=max(ans,f[temp.t]); 56 if(i==m-1 || temp.len!=edge[i+1].len) 57 { 58 while(pos<=i) 59 { 60 dp[edge[pos].t]=f[edge[pos].t]; 61 pos++; 62 } 63 } 64 } 65 printf("%d\n",ans); 66 } 67 68 int main() 69 { 70 read(); 71 work(); 72 }