zoukankan      html  css  js  c++  java
  • 【GRYZ模拟赛】GRYZ就餐时刻

    Description

    寒假,大家都回家过年去了,只有GRYZ苦逼的竞赛生们还在学校上课。众所周知,有人的地方就需要有饭,但是食堂的大爷们都回家了,我们只能依靠外卖。已知那是一个非常大的外卖店,有专业的盒饭生产设备,为了保证GRYZ的孩子们每顿饭能吃好吃的饭菜,它们总会将a点生产出的盒饭运往加热处加热后再运往b点装车。这些部门非常的高能,它们有时可以生产盒饭,有时又能变身成装车点(不要问我为什么)。

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

    Input

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

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

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

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

    Output

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

    Sample Input

    5 5

    1 2 3

    1 3 5

    4 1 7

    5 4 1

    5 3 1

    3

    4 2

    5 3

    2 3

    Sample Output

    10

    13

    -1

    HINT

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

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

    20%的数据,q=1

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

    q≤1000001≤u,v≤n1≤w≤10000

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

    题解

    其实写这个题的过程非常坎坷,因为我不会写dij,于是,考试的时候,我先自己造了一个dij,然后出乎意料(hhh)的造错了,于是两天后(就是今天)我又认真的写(zao)了一个,但是又错了,因为我根本就不会dij。。。

    然后,我开始的时候犯了这样一个**的错误

        flag[1] = true;
        dist[1] =0;
        for (int i=head[1];i;i=e[i].next)
            dist[e[i].to] = e[i].w;

    于是遇到重边重边重边啊重边重边重边就要看rp了。。。因为从1出发的边不一定扫到的最后一条就是最短啊!

    实际上应该是这样的。。  (感谢世界上最机智的小敏颜!我爱小敏颜!)

        dist[1] =0;

    错就错在,我根本不会写dij!!!

    正解:跑两个dij。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int MAXM=100010;
    const int MAXN=3010;
    int head[MAXN]={0},head2[MAXN]={0};
    int dist[MAXN]={0},dist2[MAXN]={0};
    bool flag[MAXN]={false},flag2[MAXN]={false};
    struct edgenode
    {
        int next,to,w;
    }e[MAXM],e2[MAXM];
    int n,m,q,a,b,u,v,w,cnt=0,cnt2=0;
    void ins1(int u,int v,int w)
    {
        e[++cnt].to=v; e[cnt].next=head[u]; e[cnt].w=w; head[u] = cnt;
    }
    void ins2(int u,int v,int w)
    {
        e2[++cnt2].to=v; e2[cnt2].next=head2[u]; e2[cnt2].w=w; head2[u] = cnt2;
    }
    void dij()
    {
        memset(dist,127,sizeof(dist));
        dist[1] =0;
        for (int j = 1; j<=n ;j++)
        {
            int minv = 10000000,k;
            for (int i=1;i<=n;i++)
                if (!flag[i] && dist[i]< minv)
                {
                    minv=dist[i];
                    k=i;
                }
            flag[k] = true;
            for (int i=head[k];i;i=e[i].next)
            {
                int v = e[i].to;
                if (!flag[v])
                {
                    if (dist[v] > dist[k]+e[i].w)
                        dist[v] = dist[k]+e[i].w;
                }
            }
        }
    }
    void dij2()
    {
        memset(dist2,127,sizeof(dist2));
        dist2[1] =0;
        for (int j = 1; j<=n ;j++)
        {
            int minv = 10000000,k;
            for (int i=1;i<=n;i++)
                if (!flag2[i] && dist2[i]< minv)
                {
                    minv=dist2[i];
                    k=i;
                }
            flag2[k] = true;
            for (int i=head2[k];i;i=e2[i].next)
            {
                int v = e2[i].to;
                if (!flag2[v])
                {
                    if (dist2[v] > dist2[k]+e2[i].w)
                        dist2[v] = dist2[k]+e2[i].w;
                }
            }
        }
    }
    int main()
    {
        freopen("eat.in","r",stdin);
        freopen("eat.out","w",stdout);
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            ins1(u,v,w);
            ins2(v,u,w);
        }
        dij();
        dij2();
        scanf("%d",&q);
        for (int i=1;i<=q;i++)
        {
            scanf("%d%d",&a,&b);
            if (dist2[a]!=2139062143 && dist[b]!=2139062143)
                 printf("%d
    ",dist2[a]+dist[b]);
             else printf("-1
    ");
        }
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

    附上我考试的时候乱造的dij,我觉得挺有纪念意义的。。。

    /*还拼错了↓。。。看看我多么认真的写了注释。。(因为造完怕自己看不懂)*/
    void dijstra()
    {
        int minv = 10000000,mini=0;
        for (int k=1;k<=n;k++)
            if (vis[k])             //k的最短路已经确定 
            {
                for (int i=head[k];i;i=e[i].next)            //可以用k扩展其他点。 
                {
                    if (!vis[e[i].to])
                        if (e[i].v < minv)
                        {
                            minv = e[i].v;
                            mini = i;
                        }
                }
            }
        if (mini)
        {
            dist[e[mini].to]=dist[e[mini].from]+e[mini].v;            //所有可行的边扩展完以后找出一个最短 
            vis[e[mini].to] = true;
            dijstra();
        }
    }
    /*还写得有模有样的。。6死我了!*/ 
    非常不好意思的折叠了。。。
  • 相关阅读:
    160422、Highcharts后台获取数据
    160421、MyBatis批量插入数据
    微信小程序wx:for循环
    【小程序】获取到的e.target与e.currentTarget区别
    微信小程序如何像vue一样在动态绑定类名
    发布 Vant
    ZanUI-WeApp -- 一个颜值高、好用、易扩展的微信小程序 UI 库
    微信小程序 使用wxParse解析html
    精通移动端布局
    axios interceptors 拦截 , 页面跳转, token 验证 Vue+axios实现登陆拦截,axios封装(报错,鉴权,跳转,拦截,提示)
  • 原文地址:https://www.cnblogs.com/liumengyue/p/5210695.html
Copyright © 2011-2022 走看看