【BZOJ1003】【ZJOI2006】物流运输trans 最短路预处理+动态规划

来源:互联网 发布:axure 浏览器插件 mac 编辑:程序博客网 时间:2024/05/22 01:29

链接:

#include <stdio.h>int main(){    puts("转载请注明出处[vmurder]谢谢");    puts("网址:blog.csdn.net/vmurder/article/details/44569117");}

题解:

首先我们跑出fi,j表示i到j这些天都是相同路线的最小代价。
然后暴力维护gi表示前i天最小代价。

fi,j可以枚举ij,暴力处理哪些点不能用,然后跑最短路。
时间复杂度
暴力处理废点O(n3m)
SPFA 是O(n2spfa)大约O(n2m2)

反正能过。
然后暴力处理废点部分可以缩掉一个n降低时间复杂度上限。
就是类似利用单调性质哒。每次枚举i后都单调处理。详见代码。

代码:

p、n、m、y:天数、点数、边数、改路代价。

#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 110#define M 1300#define inf 0x3f3f3f3fusing namespace std;struct Eli{    int v,len,next;}e[M];int head[N],cnt;inline void add(int u,int v,int len){    e[++cnt].v=v;    e[cnt].len=len;    e[cnt].next=head[u];    head[u]=cnt;}bool Dida[N],in[N];int dist[N];queue<int>q;inline void spfa(){    memset(dist,0x3f,sizeof dist);    int i,u,v;    q.push(1),dist[1]=0;    while(!q.empty())    {        u=q.front(),in[u]=0,q.pop();        for(i=head[u];i;i=e[i].next)        {            v=e[i].v;            if(Dida[v])continue;            if(dist[v]>dist[u]+e[i].len)            {                dist[v]=dist[u]+e[i].len;                if(!in[v])q.push(v),in[v]=1;            }        }    }    return ;}int n,m,p,y;bool dida[N][N];int f[N][N],g[N];int main(){    freopen("test.in","r",stdin);    int i,j,k;    int a,b,c;    scanf("%d%d%d%d",&p,&n,&y,&m);    while(m--)    {        scanf("%d%d%d",&a,&b,&c);        add(a,b,c),add(b,a,c);    }    scanf("%d",&m);    while(m--)    {        scanf("%d%d%d",&a,&b,&c);        for(i=b;i<=c;i++)dida[a][i]=1;    }    for(i=1;i<=p;i++)    {        memset(Dida,0,sizeof Dida);        for(j=i;j<=p;j++)        {            for(k=1;k<=n;k++)                Dida[k]|=dida[k][j];            spfa();            f[i][j]=dist[n];        }    }    for(i=1;i<=p;i++)g[i]=(f[1][i]<inf)?(f[1][i]*i):inf;    for(i=1;i<=p;i++)for(j=0;j<i;j++)if(f[j+1][i]<inf)        g[i]=min(g[i],g[j]+f[j+1][i]*(i-j)+y);    printf("%d\n",g[p]);    return 0;}
0 0
原创粉丝点击