zoukankan      html  css  js  c++  java
  • hdu6181 Two Paths(次短路)

    Problem Description
    You are given a undirected graph with n nodes (numbered from 1 to n) and m edges. Alice and Bob are now trying to play a game.
    Both of them will take different route from 1 to n (not necessary simple).
    Alice always moves first and she is so clever that take one of the shortest path from 1 to n.
    Now is the Bob’s turn. Help Bob to take possible shortest route from 1 to n.
    There’s neither multiple edges nor self-loops.
    Two paths S and T are considered different if and only if there is an integer i, so that the i-th edge of S is not the same as the i-th edge of T or one of them doesn’t exist.

    Input
    The first line of input contains an integer T(1 <= T <= 15), the number of test cases.
    The first line of each test case contains 2 integers n, m (2 <= n, m <= 100000), number of nodes and number of edges. Each of the next m lines contains 3 integers a, b, w (1 <= a, b <= n, 1 <= w <= 1000000000), this means that there’s an edge between node a and node b and its length is w.
    It is guaranteed that there is at least one path from 1 to n.
    Sum of n over all test cases is less than 250000 and sum of m over all test cases is less than 350000.

    Output
    For each test case print length of valid shortest path in one line.

    Sample Input
    2
    3 3
    1 2 1
    2 3 4
    1 3 3
    2 1
    1 2 1

    Sample Output
    5
    3

    Hint
    For testcase 1, Alice take path 1 - 3 and its length is 3, and then Bob will take path 1 - 2 - 3 and its length is 5.
    For testcase 2, Bob will take route 1 - 2 - 1 - 2 and its length is 3

    分析:
    这道题又和Tyvj1293不一样了,
    我们必须找到一条最短路,因此每条路可以重复走

    我一开始非常simple,认为如果只有一条路可以到达终点
    那次短路就是dis[t]*3 (到达终点–回来–再次到达终点)

    后来发现不是这么简单的,
    那我们把最短路中的最短一条边重复走三遍不就行了吗
    但是这样我们也可以hack掉:
    这里写图片描述

    那怎么办呢
    我们不光要套一个次短路模板
    同时还要再加一个特判,

    找到与最短路径上的点有关的路径中最短的一条边,

    重复走这条边就可以了

    tip

    做题的时候还是要多思考,
    找到复杂的样例,从中探寻规律

    这里写代码片
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define ll long long
    
    using namespace std;
    
    const ll INF=1e16;
    const int N=100010;
    int q[N<<1],tou,wei,n,m,st[N],tot,pre[N],s,t;
    struct node{
        int x,y,nxt;
        ll v;
    };
    node way[N*6];
    ll dis[N],ans1,ans2;
    bool p[N];
    
    void add(int u,int w,int z)
    {
        tot++;
        way[tot].x=u;way[tot].y=w;way[tot].v=(ll)z;way[tot].nxt=st[u];st[u]=tot;
        tot++;
        way[tot].x=w;way[tot].y=u;way[tot].v=(ll)z;way[tot].nxt=st[w];st[w]=tot;
    }
    
    ll spfa(int s,int t)
    {
        for (int i=1;i<=n;i++) dis[i]=INF,p[i]=1,pre[i]=0;
        wei=tou=0;
        q[++wei]=s;
        dis[s]=0, p[s]=0;
        do
        {
            int r=q[++tou];
            for (int i=st[r];i;i=way[i].nxt)
                if (dis[way[i].y]>dis[r]+way[i].v)
                {
                    dis[way[i].y]=dis[r]+way[i].v;
                    pre[way[i].y]=i;
                    if (p[way[i].y])
                    {
                        p[way[i].y]=0;
                        q[++wei]=way[i].y;
                    }
                }
            p[r]=1;
        }
        while (tou<wei);
        return dis[t];
    }
    
    ll spfa2(int s,int t)
    {
        for (int i=1;i<=n;i++) dis[i]=INF,p[i]=1;
        wei=tou=0;
        q[++wei]=s;
        dis[s]=0, p[s]=0;
        do
        {
            int r=q[++tou];
            for (int i=st[r];i;i=way[i].nxt)
                if (dis[way[i].y]>dis[r]+way[i].v)
                {
                    dis[way[i].y]=dis[r]+way[i].v;
                    if (p[way[i].y])
                    {
                        p[way[i].y]=0;
                        q[++wei]=way[i].y;
                    }
                }
            p[r]=1;
        }
        while (tou<wei);
        return dis[t];
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while (T--)
        {
            memset(st,0,sizeof(st));
            tot=0;
            scanf("%d%d",&n,&m);
            s=1; t=n;
            for (int i=1;i<=m;i++)
            {
                int u,w,z;
                scanf("%d%d%d",&u,&w,&z);
                add(u,w,z);
            }
            ans1=spfa(s,t); 
    
            ans2=INF;
            ll o=INF;
            for (int i=t;i!=s;i=way[pre[i]].x)
            {
                ll u=way[pre[i]].v;
                if (u<o) o=u;
                way[pre[i]].v=INF;
                ll an=spfa2(s,t);
                if (an<ans2&&an!=ans1) ans2=an;
                way[pre[i]].v=u; 
    
                if (way[pre[i]].x!=0)
                    for (int j=st[way[pre[i]].x];j;j=way[j].nxt)
                        if (way[j].v<o) o=way[j].v; 
            }
    
            for (int j=st[t];j;j=way[j].nxt)
                if (way[j].v<o) o=way[j].v; 
            if (ans1+2*o<ans2) ans2=ans1+2*o;
    
            printf("%lld
    ",ans2);
        }
        return 0;
    } 
  • 相关阅读:
    AngularJS各种'service'的区别
    js 斐波那契数列实现
    Mac下Apache+MySQL+PHP开发环境安装过程
    原生封装的js前端工具库(包含了jquery的常用功能)
    BFC 神奇背后的原理
    CSS清浮动处理(Clear与BFC)
    JavaScript实现 页面滚动图片加载(懒加载)
    CodeForce 814B
    排序算法
    uva1610
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673231.html
Copyright © 2011-2022 走看看