1. 程式人生 > >2017多校第10場 HDU 6181 Two Paths 次短路

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

-1 pat sca new tin add str clu operator

題目鏈接: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 次短路