2017多校第10场 HDU 6181 Two Paths 次短路

Posted Lsxxxxxxxxxxxxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017多校第10场 HDU 6181 Two Paths 次短路相关的知识,希望对你有一定的参考价值。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6181

题意:给一个图,求出次短路。

解法:我之前的模板不能解决这种图,就是最短路和次短路相等的情况,证明这题数据还是水了。下来我修改了一下次短路的,就可以避免这种情况了。提供一个sample 4 4

(1,2,1)( 1, 3,1) (2 4,1) (3 ,4,1)。这组的正确答案是2,算法就来看代码吧。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL maxn = 100010;
LL n, m;
LL ST, EN;
LL num, pos[maxn];
LL vis[maxn][2];
LL cnt[maxn][2], dis[maxn][2];
struct node1
{
    LL en, val, next;
    node1(LL en = 0, LL val = 0, LL next = 0): en(en), val(val), next(next) {}
} E[maxn * 2];
struct node
{
    LL id;
    LL val;
    LL flag; //最短/次短
    node(LL id = 0, LL val = 0, LL flag = 0): id(id), val(val), flag(flag) {}
    friend bool operator <(node x, node y)
    {
        return x.val > y.val;
    }
};
void add(LL st, LL en, LL val)
{
    E[num] = node1(en, val, pos[st]);
    pos[st] = num++;
}
void dij()
{
    dis[ST][0] = 0;
    cnt[ST][0] = 1;
    priority_queue<node>q;
    q.push(node(ST, 0, 0));
    while (!q.empty())
    {
        node now = q.top();
        q.pop();
        LL val = now.val;
        LL u = now.id ;
        LL flag = now.flag;
        if (vis[u][flag]) continue;
        vis[u][flag] = 1;
        for (LL i = pos[u]; i != -1; i = E[i].next)
        {
            LL v = E[i].en;
            LL newlen = val + E[i].val;
            if (newlen <= dis[v][0]) //新路径比原最短路更小
            {
                if (dis[v][0] != INF) //如果当前点的最短路曾更新过
                {
                    //那么不仅更新最短,也要更新次短
                    dis[v][1] = dis[v][0];
                    cnt[v][1] = cnt[v][0]; //次短路条数等于原来的最短路条数
                    q.push(node(v, dis[v][1], 1)); //入队,当前点距离更新,之后的也会更新
                }
                dis[v][0] = newlen; //否则仅更新最短路
                cnt[v][0] = cnt[u][flag]; //更新最短路条数,最短路条数由u点得到,u点状态由flag标记
                q.push(node(v, newlen, 0));
            }
            else if (newlen == dis[v][0])
                cnt[v][0] += cnt[u][flag]; //增加最短路条数
            else if (newlen == dis[v][1])
                cnt[v][1] += cnt[u][flag]; //增加次短路条数
            else if (newlen < dis[v][1]) //新路径大于最短路,但是小于次短路,更新次短路
            {
                dis[v][1] = newlen;
                cnt[v][1] = cnt[u][flag]; //次短路条数由u点得
                q.push(node(v, dis[v][1], 1));
            }
        }
    }
}
void init()
{
    num = 0;
    memset(cnt, 0, sizeof(cnt));
    memset(vis, 0, sizeof(vis));
    memset(E, 0, sizeof(E));
    memset(pos, -1, sizeof(pos));
    memset(dis, 0x3f, sizeof(dis));
}

int main()
{
    LL T;
    scanf("%lld", &T);
    while(T--)
    {
        init();
        scanf("%lld %lld", &n,&m);
        while(m--){
            LL u, v, w;
            scanf("%lld%lld%lld", &u,&v,&w);
            add(u, v, w);
            add(v, u, w);
        }
        ST = 1;
        EN = n;
        dij();
        printf("%lld\n", dis[EN][1]);
    }
    return 0;
}

 

以上是关于2017多校第10场 HDU 6181 Two Paths 次短路的主要内容,如果未能解决你的问题,请参考以下文章

2017多校第6场 HDU 6097 Mindis 计算几何,圆的反演

2017多校第10场 HDU 6172 Array Challenge 猜公式,矩阵幂

2017多校第10场 HDU 6180 Schedule 贪心,multiset

2017多校第10场 HDU 6178 Monkeys 贪心,或者DP

2017多校第7场 HDU 6128 Inverse of sum 推公式或者二次剩余

2017多校第6场 HDU 6105 Gameia 博弈