[BZOJ1003][ZJOI2006]货物运输

来源:互联网 发布:美国读研gpa算法 编辑:程序博客网 时间:2024/05/01 14:15

SPFA处理出i天到j天路线不变的最小值,设f[i]表示1到i天的最小值,枚举改变路线的那一天转移即可。

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<iostream>#include<cassert>#include<map>#include<climits>#include<vector>#include<queue>#include<cmath>#define DB double#define X first#define Y second#define MP make_pair#define INF 0x3f3f3f3f#define LL long long#define pii pair<int,int>#define pb push_back#define pll pair<LL,LL>#define DEBUG(...) fprintf(stderr,__VA_ARGS__)using namespace std;template<typename T>void Read(T& x){    x=0;char c;int flag=0,sgn=1;    while(c=getchar())    {        if(c=='-')sgn=-1;        else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;        else if(flag)break;    }    x*=sgn;}const int MAXN=110,MAXD=32,MAXM=MAXD*MAXD;int w[MAXM],first[MAXD],to[MAXM],next[MAXM],dis[MAXD],inq[MAXD],e;//about Graphint valid[MAXD];vector<int> G[MAXN];vector<pii> forb[MAXD];int k,E,n,m,d;LL cost[MAXN][MAXN],f[MAXN];void add(int u,int v,int c){    next[e]=first[u];first[u]=e;to[e]=v;w[e]=c;++e;    next[e]=first[v];first[v]=e;to[e]=u;w[e]=c;++e;}void SPFA(){    for(int i=0;i<MAXD;i++)dis[i]=INF;    dis[1]=0;    queue<int>  q;    q.push(1);    inq[1]=1;    while(!q.empty())    {        int u=q.front();q.pop();        inq[u]=0;        for(int i=first[u];i!=-1;i=next[i])        {            int v=to[i];            if(!valid[v])continue;            if(dis[v]>dis[u]+w[i])            {                dis[v]=dis[u]+w[i];                if(!inq[v])                {                    q.push(v);                    inq[v]=1;                }            }        }    }}int main(){    freopen("trans.in","r",stdin);    freopen("trans.out","w",stdout);    memset(first,-1,sizeof(first));    Read(n),Read(m),Read(k),Read(E);    for(int i=1;i<=E;i++)    {        int u,v,c;        Read(u),Read(v),Read(c);        add(u,v,c);    }    Read(d);    for(int i=1;i<=d;i++)    {        int u,a,b;        Read(u),Read(a),Read(b);        forb[u].pb(MP(a,b));    }    for(int i=1;i<=n;i++)        for(int j=i;j<=n;j++)        {            memset(valid,-1,sizeof(valid));            for(int l=1;l<=m;l++)                for(int ii=0;ii<forb[l].size();ii++)//坑!                if(!(forb[l][ii].Y<i||forb[l][ii].X>j))                    valid[l]=0;            SPFA();//          assert(dis[m]<=INF);            if(dis[m]<INF)cost[i][j]=(j-i+1)*(LL)dis[m];            else cost[i][j]=INF;            //cout<<cost[i][j]<<endl;        }    for(int i=0;i<MAXN;i++)f[i]=LONG_LONG_MAX/10;    f[0]=0;    //f[1]=cost[1][1];    for(int i=1;i<=n;i++)    {        for(int j=0;j<i;j++)        {            assert(f[j]<INF);            f[i]=min(f[i],f[j]+cost[j+1][i]+k);        }    }    cout<<f[n]-k<<endl;}
0 0