标算是贪心,我写了个差分约束?????
设dist[i]表示1-i号土地种的树的总棵数,考虑以下几种约束条件:
1)dist[y]>=dist[x]+z,即x号土地至y号土地间至少种了z棵树
2)dist[i-1]>=dist[i]-1,即i号土地最多比i-1号土地多种1棵树
3)dist[i]>=dist[i-1]+0,即i号土地不会比i-1号土地种的树少
建图后直接跑单源最长路即可。
参考代码如下:
1 #include<iostream> 2 #include<queue> 3 #include<cstring> 4 #include<cstdio> 5 #define N 30005 6 #define M 300005 7 using namespace std; 8 int v[M],w[M],head[M],nxt[M],dist[M],n,m,cnt,x,y,z,maxn; 9 bool vis[N]; 10 int read() 11 { 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 15 return x*f; 16 } 17 void add(int a,int b,int c) 18 { 19 v[++cnt]=b; 20 w[cnt]=c; 21 nxt[cnt]=head[a]; 22 head[a]=cnt; 23 } 24 void spfa(int s) 25 { 26 //memset(dist,20,sizeof(dist)); 27 queue<int>q; 28 dist[s]=0; 29 q.push(s); 30 vis[s]=1; 31 while(!q.empty()) 32 { 33 int c=q.front(); 34 q.pop(); 35 vis[c]=0; 36 for(int i=head[c];i;i=nxt[i]) 37 { 38 int y=v[i]; 39 if(dist[y]<dist[c]+w[i]) 40 { 41 dist[y]=dist[c]+w[i]; 42 if(!vis[y]) 43 { 44 q.push(y); 45 vis[y]=1; 46 } 47 } 48 } 49 } 50 //for(int i=1;i<=n;i++)cout<<dist[i]-dist[i-1]<<" "; 51 //cout<<endl; 52 } 53 int main() 54 { 55 n=read();m=read(); 56 for(int i=1;i<=m;i++) 57 { 58 x=read();y=read();z=read(); 59 maxn=max(maxn,y); 60 //dist[y]>=dist[x]+z 61 add(x,y+1,z); 62 } 63 for(int i=1;i<=n;i++) 64 { 65 //dist[i-1]>=dist[i]-1 66 //dist[i-1]>=dist[i]-1 67 add(i,i-1,-1); 68 //dist[i]>=dist[i-1]+0 69 add(i-1,i,0); 70 } 71 for(int i=1;i<=n;i++) 72 { 73 dist[i]=-21374404; 74 add(0,i,0); 75 } 76 spfa(0); 77 cout<<dist[maxn+1]; 78 return 0; 79 }