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;
}

 

posted @ 2017-08-27 09:27  zxycoder  阅读(184)  评论(0编辑  收藏  举报