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\n",dis[n]); 70 }
时间: 2024-11-04 17:19:58