codevs 种树3

codevs上的题目,自从wikioi改名后,就不怎么做题了。

这道题的话注释在代码中就可以了,还是求最长路,相较返回如果中间可以种多个的话,那就种越多越好,因为这样可以减少种的棵树,

所以这个i与i-1连一条负棵树的边,这样正的连0的边,以及范围的棵树边就可以了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<cstring>
 7 using namespace std;
 8 
 9 const int NN=500007,INF=1e9+7;
10 
11 int n,m,a[NN],tot;
12 int cnt=0,head[NN],next[NN*4],rea[NN*4],val[NN*4];
13 int dis[NN];
14 bool flag[NN];
15 void add(int u,int v,int w)
16 {    
17     cnt++;
18     next[cnt]=head[u];
19     head[u]=cnt;
20     rea[cnt]=v;
21     val[cnt]=w;
22 }
23 void spfa()
24 {
25     queue<int>q;
26     for(int i=1;i<=n;i++)
27         dis[i]=-INF;
28     dis[0]=0,flag[0]=1;
29     q.push(0);
30     while(!q.empty())
31     {
32         int u=q.front();
33         q.pop();
34         flag[u]=0;
35         for(int i=head[u];i!=-1;i=next[i])
36         {
37             int v=rea[i],fee=val[i];
38             if(dis[v]<dis[u]+fee)
39             {
40                 dis[v]=dis[u]+fee;
41                 if(!flag[v])
42                 {
43                     q.push(v);
44                     flag[v]=1;
45                 }
46             }
47         }
48     }
49 }
50 int main()
51 {
52     memset(head,-1,sizeof(head));
53     scanf("%d%d",&n,&m);
54     for(int i=1;i<=n;i++)
55         scanf("%d",&a[i]);
56     int x,y,z;      
57     for(int i=1;i<=m;i++)
58     {
59         scanf("%d%d%d",&x,&y,&z);
60         add(x-1,y,z);
61     }
62     for(int i=1;i<=n;i++)
63     {
64         add(i-1,i,0);
65         add(i,i-1,-a[i]);
66     }
67     spfa();
68     
69     printf("%d
",dis[n]);
70 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/7429727.html