1003: [ZJOI2006]物流运输

挺水的。预处理一下一段时间内的最短路,dp即可

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=105,M=25;
bool tong[N][M],vis[M],tt[M];
int dp[N],ycl[N][N],son[M],nedge,n,m,K,E,P,s1,s2,s3,dist[M],oo=1000000000,que[M];
struct edge{
    int nextt,ed,di;
}e[810];
inline void aedge(int a,int b,int c){
    e[++nedge].nextt=son[a];
    son[a]=nedge;
    e[nedge].ed=b;
    e[nedge].di=c;
}
inline int  read()//不管是正负数,都可以 
{
    int x = 0; char ch = getchar(); bool positive = 1;
    for (; !isdigit(ch); ch = getchar())    if (ch == '-')  positive = 0;
    for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
    return positive ? x : -x;
}
inline void write(int a){
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
inline void writeln(int a){
    write(a); puts("");
}
int spfa(int s,int t,int day1,int day2){int i;
    for(i=1;i<=m;i++){dist[i]=oo;vis[i]=que[i-1]=tt[i]=0;}
    for(i=day1;i<=day2;i++)for(int j=1;j<=m;j++)tt[j]|=tong[i][j];
    int tot=1; int l=0; int r=0; que[0]=s; vis[s]=true; dist[s]=0;
    while(tot){
        int k=que[l]; //if(day==4)cout<<k<<" "<<tong[4][5]<<endl;
        vis[k]=false;
        if (++l==m) l=0;
        tot--; i=son[k];
        while (i) {
            if (dist[e[i].ed]>dist[k]+e[i].di&&(!tt[e[i].ed])) 
            {
                dist[e[i].ed]=dist[k]+e[i].di;
                if (vis[e[i].ed]==0) {
                    r++; r%=m;
                    que[r]=e[i].ed; tot++; vis[e[i].ed]=true;
                }
            }
            i=e[i].nextt;
        }
    }
    return dist[t];
}
int main(){
    n=read(); m=read(); K=read(); E=read();
    for(int i=1;i<=E;i++){
        s1=read(); s2=read(); s3=read(); aedge(s1,s2,s3); aedge(s2,s1,s3);
    }
    P=read();
    for(int i=1;i<=P;i++){
        s1=read(); s2=read(); s3=read();
        for(int j=s2;j<=s3;j++)tong[j][s1]=true;
    }
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)ycl[i][j]=spfa(1,m,i,j); 
    dp[0]=-K;
    for(int i=1;i<=n;i++){dp[i]=oo;
        for(int j=0;j<i;j++){
            if(ycl[j+1][i]<=(oo>>1))dp[i]=min(dp[i],dp[j]+K+ycl[j+1][i]*(i-j));
        }
        //cout<<dp[i]<<" "<<i<<endl;
    }
    cout<<dp[n]<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值