题意:给出了城市数n,以及街道数m(街道是双向均可通行的), 对于每一条街mi,给出它的两端的城市,以及所能承载的最大货物运输量。
要求输出,从城市1到城市n,最多能运输多少货物。
分析:无向、带权图的单源最短路问题。 但这里路径的定义变成了:这条路上权值最小的那段路 的权值(而非所有段的权值之和)。
我们的任务就是求出:每一条从1到n的路上,“路径” 的最大值。 这样,就成了求单源最长“路径”。
//hoj 1653 //Dijkstra 单源最短路 //注意此题中路长的定义变成了,各段路的权值的最小值 #include <iostream> #include <cstdio> #include <memory.h> #include <climits> #define N 1005 #define MinN 0 using namespace std; int map[N][N]; bool used[N]; int dis[N]; int main() { int caseNum; scanf("%d",&caseNum); for(int t=1; t<=caseNum; t++) { memset(map,0,sizeof(map)); //初始化为零,是因为不相邻的两个点间的通货能力为0(不要惯性思维初始化为无穷大) int n,m; scanf("%d %d",&n,&m); for(int i=0; i<m; i++) { int s,e; scanf("%d %d",&s,&e); scanf("%d",&map[s][e]); map[e][s]=map[s][e]; } memset(used,0,sizeof(used)); for(int i=1; i<=n; i++) { dis[i]=map[1][i]; //dis[i]储存点i到源点1的路径 } used[1]=1; int count=n; while(count--) { int m=MinN; int v; for(int i=2; i<=n; i++) { if(!used[i]&&m<dis[i]) { //找到与源点1通货能力最大的,且尚未访问过的点。这是一种贪心的思想。 m=dis[i]; v=i; } } used[v]=1; for(int j=1; j<=n; j++) { dis[j]=max(dis[j],min(dis[v],map[v][j])); //转移方程 //min(dis[v],map[v][j])获得的是从1到v再到j这条路的“路径”。 //max()用来更新点1到点j的最长路径。这条路可能是从1直接到j,也可能是从1到v再到j } printf("Scenario #%d:\n",t); printf("%d\n\n",dis[n]); } return 0; }