http://poj.org/problem?id=3463
/* 题目类型;最短路-—最短路和相差一个单位的次短路的条数和 //本题关键在于理解Dijkstra的贪心思想 解题思路: 本题若开始直接在Dijkstra中加入针对加1的递推式, 必须在Dijkstra的过程中加入DFS, 很繁琐. 改换求次短路, 然后判断次短路是否比最短路长1. 解法一、A*求第K短路,把前面K条路都求出来,pku 2449 ,但是据说这个题的最后答案超过10^8,把路全部找出来肯定会爆priority_queue 解法二、 改进Dijkstra算法,。将状态扩展到二维,第一维仍然是顶点编号,第二维的长度为2,分别用于记录最短路和次短路。 这样的数据有两个,dist[][2]记录距离,cnt[][2]计数。 更新状态时: 1)新值小于最短路径长:更新最短路径长,计数;次短路径长,计数 2)新值等于最短路径长:更新最短路径计数 3)新值大于最短路径长,小于次短路径长:更新次短路径长,计数 4)新值等于次短路径长:更新次短路径计数 值得注意的是,题目图有重边,所以不能用邻接矩阵存储。 本题可以与UESTC 1053 Shortest road(只求最短路的条数,但最短路中的路径只有一条不同即可),HDU 1459(只求最短路的条数,但是不同最短路的最短路的不能包含相同的路)。本题和UESTC 1053 Shortest road最短路均可重复,只有一条不同即可 */ #include<iostream> #include<vector> using namespace std; const int inf = 0x7fffffff; const int MAXN = 1001;//最多顶点数 const int MAXM = 10001;//最多边数 struct Edge { int v; int w; }; int n, m;//顶点数,边数 int edgenum; int src, dest;//起点与终点 vector<Edge> adj[MAXN]; int d[MAXN][2];//d[i][0]表示从起点到i的最短距离,d[i][1]表示从起点到i的次短距离 bool visit[MAXN][2]; int cnt[MAXN][2];//cnt[i][0]表示从起点到i的最短路径的条数 int dijkstrea() { int i, j, k, v, min; for(i=1; i<=n; i++)//初始化d[][],cnt[][],visit[][] { d[i][0] = inf; d[i][1] = inf; visit[i][0] = false; visit[i][1] = false; cnt[i][0] = inf; cnt[i][1] = inf; } //对原点的初始化 d[src][0] = 0; cnt[src][0] = 1; //final[src][0] = true; 此处不能将final[src][0]的值赋值为true,因为本题使用邻接表实现,d[i][0],d[i][1]没有初始化为与源点的距离 for(i=1; i<2*n; i++)//此处要找最短路径与次短路径,因此要循环2*n次 { min = inf; v = -1; for(j=1; j<=n; j++) { if(!visit[j][0] && d[j][0] < min)//找最短路径 { min = d[j][0]; k = 0; v = j; } else if(!visit[j][1] && d[j][1] < min)//找次短路径 { min = d[j][1]; k = 1; v = j; } } if(v == -1) break; visit[v][k] = true; for(j=0; j<adj[v].size(); j++) { int u = adj[v][j].v; int w = adj[v][j].w; if(d[u][0] > min + w)//新值比最短路径小,则更新最短路径,计数;次短路径,计数 { d[u][1] = d[u][0];//更新次短路径 d[u][0] = min + w;//更新最短路径 cnt[u][1] = cnt[u][0];//更新次短路径计数 cnt[u][0] = cnt[v][k];//更新最短路径计数 } else if(d[u][0] == min + w)//新值等于最短路径,则更新最短路径的计数 { cnt[u][0] += cnt[v][k]; } else if(d[u][1] > min + w)//新值小于次短路径,则更新次短路径与计数 { d[u][1] = min + w; cnt[u][1] = cnt[v][k]; } else if(d[u][1] == min + w)//新值等于次短路径,则更新次短路径的计数 { cnt[u][1] += cnt[v][k]; } } } int num = cnt[dest][0];//表示最短路径的条数 if(d[dest][0] + 1 == d[dest][1])//表示次短路径与最短路径是否差一 num += cnt[dest][1]; return num; } int main() { // freopen("in.txt","r",stdin); int i, a, b, w, t; Edge temp; scanf("%d", &t); while(t--) { scanf("%d %d", &n, &m); for(i=1; i<=n; i++) { adj[i].clear(); } for(i=1; i<=m; i++) { scanf("%d %d %d", &a, &b, &w); temp.v = b; temp.w = w; adj[a].push_back(temp); } scanf("%d%d", &src, &dest); printf("%d/n", dijkstrea()); } return 0; }