寒假测试之食堂

食堂有专业的盒饭生产设备,为了人员每顿饭能吃好吃的饭菜,它们总会将a点生产出的盒饭运往加热处加热后再运往b点装车。这些部门非常的高能,它们有时可以生产盒饭,有时又能变身成装车点(不要问我为什么)。

有些部门之间有专门的传送带连接,店长是个非常珍惜时间的人,他希望盒饭从生产出来到运走所花费的时间尽可能的短,但是店长又是一个超级懒人,所以他把计算的工作交给了你

【输入格式】

第一行两个整数n、m,n表示部门数量,m表示传送带数量。出于方便,1号部门是加热处。

接下来m行,每行三个整数u、v、w,表示有一条从u部门到v部门的传送带,传送过去需要w个单位时间。注意传送带是单向的。

接下来一个整数q,表示有q次运送。

接下来q行,每行两个数a、b,表示这一次要将产品从a部门运送到b部门。

【输出格式】

输出q行,每行一个整数,表示这次运送最少需要的时间。若没有传送方案,输出-1。

【样例输入】

5 5

1 2 3

1 3 5

4 1 7

5 4 1

5 3 1

3

4 2

5 3

2 3

【样例输出】

10

13

-1

【数据规模与约定】

30%的数据,n≤100,m≤500,w=1

60%的数据,n≤100,m≤5000

另20%的数据,q=1

100%的数据,2≤n≤3000,m≤100000,2≤a,b≤n,

q≤100000,1≤u,v≤n,1≤w≤10000

有些部门之间可能有多条传送带。

#include<cstdio>
#include<cstring>
int head[2][6000],next[2][3000],xx[2][6000],to[2][6000],dist[2][3000];/*
    head[][i]与第i条边具有相同开始节点的上一条边;
    next[][i]第i个点最后读入的边;
    xx[][i]第i条边的权值(可以用一个数组);
    to[][i]第i条边的终点;
    dist[][i]第1个点到第i个点的距离*/
int x,y,z,bh=0,q,n,m;
bool f[6001];
void dj(int x)
{
    for(int i=2;i<=n;i++){
        int min=2100000000,minn;
        for(int j=next[x][1];j!=0;j=head[x][j]){
            if(!f[to[x][j]]&&dist[x][to[x][j]]&&dist[x][to[x][j]]<min){//找从第一个点出发的最短边;
                  min=dist[x][to[x][j]];
                  minn=j;
          }
        }          
        f[to[x][minn]]=true;
        for(int j=next[x][to[x][minn]];j!=0;j=head[x][j]){             //从第minn个点开始更新;
            if(!f[to[x][j]]&&((dist[x][to[x][minn]]+xx[x][j]<dist[x][to[x][j]])||(dist[x][to[x][j]]==0))){
                dist[x][to[x][j]]=dist[x][to[x][minn]]+xx[x][j];
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        head[0][i]=next[0][x];     //边表
        next[0][x]=i;
        xx[0][i]=z;
        to[0][i]=y;
        head[1][i]=next[1][y];     //边反向建立边表
        next[1][y]=i;
        xx[1][i]=z;
        to[1][i]=x;
    }
    x=next[0][1];f[1]=1;
    for(;x;){
        if(!dist[0][to[0][x]]||dist[0][to[0][x]]>xx[0][x]) dist[0][to[0][x]]=xx[0][x];//将与1相连的边的权值存入dist[1]中;
        x=head[0][x];
    }
    dj(0);                                   //dijkstra;
    memset(f,0,3001*sizeof(bool));
    f[1]=1;
    for(x=next[1][1];x;x=head[1][x]){
        if(!dist[1][to[1][x]]||dist[1][to[1][x]]>xx[1][x])dist[1][to[1][x]]=xx[1][x];//将与1相连的边的权值存入dist[2]中;
    }
    dj(1);                                   //dijkstra;
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&x,&y);
        if(dist[1][x]&&dist[0][y]) printf("%d
",dist[0][y]+dist[1][x]);//若x能到1,1能到y,输出最短路;
        else printf("-1
");
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/qingang/p/5211286.html