Codeforces 459E Pashmak and Graph:dp + 贪心

时间:2023-02-01 22:09:12

题目链接: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 }