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