最短路之最大点权问题
问题引入:PTA A1003
问题分析:
直接分析输入输出。
输入
-
点数n、边数m、起点st、终点ed
-
点权
-
边权
输出
- 最短路条数
- 最短路里最大点权和
题解
最短路算法无非dijkstra、Floyd、SPFA,这里以dijkstra算法为例。
在dijkstra的基础上再引入三个数组:weg[],点权,w[]记录最大点权,way[]记录最短路条数。
下面分析dij()函数:
//邻接矩阵G[][],最短路数组dis[],访问数组vis[] void dij(int st, int ed)//传入起点、终点 { //初始化(从0开始计数) for (int i = 0; i < n; ++i) { vis[i] = 0; w[i] = 0; dis[i] = G[st][i]; } w[st] = weg[st];//起点的点权 way[st] = 1;//起点到起点的路径为1 dis[st] = 0; for (int i = 0; i < n; ++i) { int x = -1, mx = inf; for (int j = 0; j < n; ++j) { if (!vis[j] && dis[j] < mx) { x = j; m = dis[j]; } } if (x == -1) return;//若x为-1,则该点与其他点都不联通。 for (int j = 0; j < n; ++j) if (!vis[j] && G[x][j] != inf) { if (dis[j] == dis[x] + G[x][j]) { //走中转站和不走中转站都一样 //那就比点权 if (w[j] < w[x] + weg[j]) w[j] = w[x] + weg[j]; way[j] += way[x]; //再加上一条从中转站过来的路 } else if (dis[j] > dis[x] + G[x][j]) {//可松弛 dis[j] = dis[x] + G[x][j]; way[j] = way[x]; //要走最短路必须走中转站,故直接覆盖。 w[j] = w[x] + weg[j]; } } } printf("%d %d", way[ed], w[ed]); }
一下为我的AC代码,与题解的命名不一致,有需者请悉知。
#include <iostream> using namespace std; const int inf = 1e7+7; const int maxn = 505; //w为邻接矩阵,n为点数,m为边数,dis为最短路 int w[maxn][maxn], n, m, dis[maxn]; //team为点权,tms记录最大点权和,way记录最短路径条数 int team[maxn], tms[maxn], way[maxn]; bool v[maxn]; void dij(int st, int end) { for (int i = 0; i < n; ++i) { dis[i] = w[st][i]; v[i] = 0; way[i] = 0; } dis[st] = 0; tms[st] = team[st]; way[st] = 1; for (int i = 0; i < n; ++i) { int x = -1, mx = inf; for (int j = 0; j < n; ++j) if (!v[j] && dis[j] < mx) { x = j; mx = dis[j]; } if (x == -1) return; v[x] = 1; for (int j = 0; j < n; ++j) if (!v[j] && w[x][j] != inf) { if (dis[j] == dis[x] + w[x][j]) { if (tms[x] + team[j] > tms[j]) tms[j] = tms[x] + team[j]; way[j] += way[x]; } else if (dis[j] > dis[x] + w[x][j]) { dis[j] = dis[x] + w[x][j]; way[j] = way[x]; tms[j] = tms[x] + team[j]; } } } printf("%d %d", way[end], tms[end]); } int main() { ios::sync_with_stdio(0); cin.tie(0); cin >> n >> m; for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) w[i][j] = inf; int a, b ,c, st, end; cin >> st >> end; for (int i = 0; i < n; ++i) cin >> team[i]; for (int i = 0; i < m; ++i) { cin >> a >> b >> c; w[a][b] = c; w[b][a] = c; } dij(st, end); return 0; }
来源:https://www.cnblogs.com/xdaniel/p/12631155.html