Codeforces 459E Pashmak and Graph:dp + 貪心

Leohh發表於2018-01-03

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

 

相關文章