[codevs1768] 种树

传送门
最近在学差分约束,看到这题就想到了差分约束
利用前缀和,就可以将问题转化为差分约束
由题可得三个不等式

d i s [ i ] d i s [ i 1 ] <= k [ i ]

d i s [ i ] d i s [ i 1 ] >= 0

d i s [ r i [ i ] ] d i s [ l i [ i ] 1 ] >= c [ i ]

由于题目求的是 d i s [ n ] d i s [ 0 ] 的最小值,所以就将不等式转化为 d i s [ x x x ] d i s [ y y y ] >= z z z 的形式,从 y y y x x x 建一条权值为 z z z 的边,建完图跑SPFA求最长路就行了。

由于忘记了第二个不等式(其实都想到了,写的时候又忘了),并且忘了初始化,WA了好久QAQ

并且大概是由于我写的vector吧,在codevs上是能过,XJOI上就T了,反面教材.JPG
等我改天有空再写写链表的吧,毕竟不会写好像还是不行的啊。

又:这是我有史以来写过最丑的blog

#include<bits/stdc++.h>
using namespace std;
const int N=500111;
int n,m,h[N],t,w,b[N];
long long dis[N];
vector<int> a[N],v[N];

void read(int &x){
    char ch=getchar();x=0;
    for(;ch<'0'||ch>'9';ch=getchar());
    for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
}

void spfa(){
    t=w=1;h[w]=0;b[0]=1;
    for(int i=1;i<=n;i++) dis[i]=-0x3f3f3f3f;
    while(t!=(w+1)%N){
        int x=h[t];
        for(int i=0;i<a[x].size();i++)
         if (dis[x]+v[x][i]>dis[a[x][i]]){
            dis[a[x][i]]=dis[x]+v[x][i];
            if (!b[a[x][i]]){
                w=(w+1)%N;
                h[w]=a[x][i];
                b[a[x][i]]=1;
             }
         }
        b[x]=0;
        t=(t+1)%N;
    }
}

int main(){
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=n;i++){
        int k;read(k);
        a[i].push_back(i-1);v[i].push_back(-k);
        a[i-1].push_back(i);v[i-1].push_back(0);
    }
    for(int i=1;i<=m;i++){
        int x,y,z;
        read(x);read(y);read(z);
        a[x-1].push_back(y);v[x-1].push_back(z);
    }
    spfa();
    printf("%lld",dis[n]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ymzqwq/article/details/80202980