1. 程式人生 > >種樹3

種樹3

返回 ext class std logs amp front names void

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 }

種樹3