zoukankan      html  css  js  c++  java
  • 匈牙利游戏

    【题目描述】

    布达佩斯的街道形成了一个弯曲的单向网络。你要参加一个赛跑,比赛中你需要穿越这些街道,从s开始,到t结束。

    要求写一个程序来计算一个从s到t的严格次短路线。

    严格次短路线可能访问某些节点不止一次,样例2是一个例子。

    【输入描述】

    第一行包含两个整数N和M,N代表布达佩斯的节点个数,M代表边的个数。节点编号从1到N。1代表出发点s,N代表终点t;

    接下来的M行每行三个整数A、B、L,代表有一条从A到B的长度为L的单向同路。你可以认为A不等于B,也不会有重复的(A,B)对。

    【输出描述】

    输出从s到t的严格次短路的长度。如果从s到t的路少于2条,输出-1。

    【样例输入】

    样例1:

    4 6

    1 2 5

    1 3 5

    2 3 1

    2 4 5

    3 4 5

    1 4 13

     

    样例2:

    2 2

    1 2 1

    2 1 1

    【样例输出】

    样例1:

    11

     

    样例2:

    3

    【数据范围及提示】

    样例1:

    有两条长度为10的最短路径(1 → 2 → 4,1 → 3 → 4)并且有一条长度为11的严格次短路径(1 → 2 → 3 → 4)。

    样例2:

    有一条长度为1的最短路径(1 → 2)并且有一条长度为3的严格次短路径(1 → 2 → 1 → 2)。

    源代码:
    
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    struct Node
    {
        int Next,To,T;
    }i[1000001];
    queue <int> Q;
    bool in[200001]={0};
    int n,m,Num(0),Head[200001];
    long long dis[200001],f[200001]; //RE真乃神坑也!
    void Add(int A,int B,int C)
    {
        i[++Num].To=B;
        i[Num].T=C;
        i[Num].Next=Head[A];
        Head[A]=Num;
    }
    void SPFA(int S)
    {
        dis[S]=0;
        in[S]=true;
        Q.push(S);
        while (!Q.empty())
        {
            int t1=Q.front();
            Q.pop();
            in[t1]=false;
            for (int a=Head[t1];a;a=i[a].Next)
            {
                int t2=i[a].To;
                if (dis[t2]>dis[t1]+i[a].T)
                {
                    f[t2]=dis[t2]; //次短路更新。
                    dis[t2]=dis[t1]+i[a].T; //最短路更新。
                    if (!in[t2])
                    {
                        Q.push(t2); //入队是因为图有了变化,是否能引起连锁反应。
                        in[t2]=true;
                    }
                }
                else
                  if (dis[t2]!=dis[t1]+i[a].T&&f[t2]>dis[t1]+i[a].T) //只更新次短路。
                  {
                    f[t2]=dis[t1]+i[a].T;
                    if (!in[t2])
                    {
                        Q.push(t2);
                        in[t2]=true;
                    }
                  }
                  else
                    if (f[t2]>f[t1]+i[a].T) //仔细想一想会发现,当dis[t2]=dis[t1]时,只得如此更新。
                    {
                        f[t2]=f[t1]+i[a].T;
                        if (!in[t2])
                        {
                            Q.push(t2);
                            in[t2]=true;
                        }
                    }
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int a=1;a<=m;a++)
        {
            int A,B,C;
            scanf("%d%d%d",&A,&B,&C);
            Add(A,B,C); //有向边表。
        }
        for (int a=1;a<=m;a++) //赋极大大大值。
          dis[a]=f[a]=1000000000;
        SPFA(1); //从起点开始。
        if (f[n]<1000000000)
          printf("%lld",f[n]);
        else
          printf("-1");
        return 0;
    }
  • 相关阅读:
    zoj-3433-Gu Jian Qi Tan
    优先队列详解(转载)
    HDU-3661-Assignments
    hdu-1052-Tian Ji -- The Horse Racing(经典)
    POJ-1456-Supermarket
    UVA-11292Dragon of Loowater
    UVA-11729-Commando War
    循环日程表 问题(递归分治)
    八数码问题
    POJ-3273 Monthly Expense (最大值最小化问题)
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5754683.html
Copyright © 2011-2022 走看看