poj 3463 最短路与次短路

来源:互联网 发布:中国和韩国的差距知乎 编辑:程序博客网 时间:2024/04/28 12:46

非常好的题目

“可能存在多条路径的情况下”

求解从指定源点到汇点的最短路和次短路

dijkstra框架结构基本不变,松弛的时候才用以下方式

/*    求s到t的最短路与次短路(这里要求只比最短路多1)的条数之和        联想到最小,次小的一种更新关系:    if(x<最小)更新最小,次小    else if(==最小)更新方法数    else if(x<次小)更新次小    else if(x==次小)更新方法数    同时记录s到u最短,次短路及方法数    用一个堆每次取最小的,更新完后再入堆    还是那个原理,第一次遇到的就是最优的,然后vi标记为真    方法数注意是加法原理,不是乘法    \    -- u -- v  所以是加法原理    /*/

单纯的单源最短路径的话,只有第一种情况

#include <iostream>#include <vector>#include <map>#include <list>#include <set>#include <deque>#include <stack>#include <queue>#include <algorithm>#include <cmath>#include <cctype>#include <cstdio>#include <iomanip>#include <cmath>#include <cstdio>#include <iostream>#include <string>#include <sstream>#include <cstring>#include <queue>using namespace std;///宏定义const int  INF = 1000000000;const int MAXN = 10010;///全局变量 和 函数int cases;int n, m;                 //顶点数,边数struct edge{int to;int len;int next;}e[MAXN];int s, t;struct node{int a;           //当前结点编号int kind;        //当前处理结点类型,0表示最短路,1表示次短路int w;           //当前结点的最小值,类似于dist[a]bool operator < (const node & b)const{return w > b.w;}}start, temp, tex;priority_queue<node> Q;int qq[1005];              //邻接表存储,本题可能存在多条路径bool vis[1005][2];int cn[1005][2],d[1005][2];//分别表示最短,次短路的数目  最短次短路的长度int dijkstra(){/*    求s到t的最短路与次短路(这里要求只比最短路多1)的条数之和        联想到最小,次小的一种更新关系:    if(x<最小)更新最小,次小    else if(==最小)更新方法数    else if(x<次小)更新次小    else if(x==次小)更新方法数    同时记录s到u最短,次短路及方法数    用一个堆每次取最小的,更新完后再入堆    还是那个原理,第一次遇到的就是最优的,然后vi标记为真    方法数注意是加法原理,不是乘法    \    -- u -- v  所以是加法原理    /    */int i, j;for (i = 0; i <= n; ++i){d[i][0] = INF;d[i][1] = INF;cn[i][0] = 0;cn[i][1] = 0;vis[i][0] = false;vis[i][1] = false;}while (!Q.empty())Q.pop();//初值start.a = s;start.w = 0;start.kind = 0;d[s][0] = 0;cn[s][0] = 1;Q.push(start);while (!Q.empty()){temp = Q.top();Q.pop();if (vis[temp.a][temp.kind])continue;vis[temp.a][temp.kind] = true;//松弛for (i = qq[temp.a]; i != 0; i = e[i].next){int tl, tj;tl = temp.w + e[i].len;        //从当前结点到下一个结点的数值tj = e[i].to;                  //下一个结点if (tl < d[tj][0]){if (d[tj][0] < d[tj][1]){d[tj][1] = d[tj][0];cn[tj][1] = cn[tj][0];tex.a = tj;tex.w = d[tj][1];tex.kind = 1;Q.push(tex);}d[tj][0] = tl;cn[tj][0] = cn[temp.a][0];tex.a = tj;tex.w = tl;tex.kind = 0;Q.push(tex);}else if (tl == d[tj][0]){cn[tj][0] += cn[temp.a][0];}else if (tl < d[tj][1]){ d[tj][1] = tl; cn[tj][1] = cn[temp.a][temp.kind]; tex.a = tj; tex.w = tl; tex.kind = 1; Q.push(tex);}else if (tl == d[tj][1]){cn[tj][1] += cn[temp.a][temp.kind];}}}//输出结果if(d[t][0] + 1 == d[t][1]) return cn[t][0] + cn[t][1];return cn[t][0];}int main(){///变量定义int i, j;scanf("%d", &cases);while (cases--){scanf("%d%d", &n, &m);memset(qq, 0, sizeof(qq));for (i = 1; i <= m; ++i){int from, to, len;scanf("%d%d%d", &from, &to, &len);e[i].to = to;e[i].len = len;e[i].next = qq[from];qq[from] = i;}scanf("%d%d", &s, &t);printf("%d\n", dijkstra());}///结束return 0;}