分析

我们可以对于每一天考虑,如果有一天改了道,那么贪心的选择也应该是最短路,而不是其它的路径。这个还是比较显然的。那么现在考虑一个线性 。令 表示考虑 从第 天的最小代价和。那么转移为 。这里引入了一个 的数组。这里表示从第 天到第 天的合法的最短路。那么我们可以先预处理 总的复杂度为 。最后 的复杂度为

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 201;
#define LL long long
const int inf = 0x3f3f3f3f;
int read() {
    int x = 0,f = 0;char ch = getchar();
    while(!isdigit(ch)) {if(ch=='-')f=1;ch = getchar();}
    while(isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();}
    return f?-x:x;
}
#define piiL pair<LL,int>
#define piii pair<int,int>
LL f[N];
int g[N][N],dis[21];
int L[N],R[N],id[N],n,m,K,E;
bool vis[21];
vector<piii>G[N];
priority_queue<piiL> q;
void solve(int s){
    memset(dis,0x3f,sizeof(dis));
    dis[s]=0;q.push(piiL(dis[s],s));while(!q.empty()){
        int x=q.top().second;q.pop();if(vis[x])continue;vis[x]=1;
        for(auto e:G[x]) {if(vis[e.first] || dis[e.first]<=dis[x]+e.second) continue;
            dis[e.first]=dis[x]+e.second;q.push(piiL(-dis[e.first],e.first));
        }
    }
}
int main() {
    n=read();m=read();K=read();E=read();
    for(int i=1,a,b,c;i<=E;i++){
        a=read();b=read();c=read();
        G[a].push_back(piii(b,c));G[b].push_back(piii(a,c));
    }
    int T=read();for(int i=1;i<=T;i++)id[i]=read(),L[i]=read(),R[i]=read();
    f[0]=0;
    for(int l=1;l<=n;l++){
        for(int r=l;r<=n;r++){
            memset(vis,0,sizeof(vis));
            for(int k=1;k<=T;k++) if(!(r<L[k]||l>R[k]))vis[id[k]]=1;
            solve(1);g[l][r]=dis[m];
        }
    }
    for(int i=1;i<=n;i++){
        if(g[1][i]<inf)f[i]=g[1][i]*i;
        else f[i]=1e18;
        for(int j=1;j<=i;j++){
            if(g[j][i]<inf)f[i]=min(f[i],f[j-1]+g[j][i]*(i-j+1)+K);
        }
    }
    cout<<f[n]<<endl;
}