題目連結: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 }