刚开始的思路是把每条边的权值处理一下 用1000005-w作为权值,然后求最短路 再求路径上的最小的那个权值
但是实际上每一次都要尽量找最大的那个权值 而不是让和最大
所以正确的做法是改变一下松弛的条件【最短路题目的核心】
然而还是不太清楚要怎么改 参考了一下题解
dijkstra 和 sfpa都写了下
还有就是 最短路的题目要注意初始化
这道题用cin会T
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<cmath> #include<map> #include<cstring> #include<queue> #include<stack> #define inf 0x3f3f3f3f using namespace std; const int maxn = 1005; int t, n, m; bool vis[maxn]; int p[maxn][maxn], d[maxn]; /*void dijkstra(int sec) { int mmax, max_num; for(int i = 1; i <= n; i++ ){ vis[i] = false; d[i] = p[sec][i]; } vis[sec] = true; d[sec] = 0; for(int i = 1; i < n; i++){ mmax = -inf; for(int j = 1; j <= n; j++){ if(!vis[j] && d[j] > mmax){ mmax = d[j]; max_num = j; } } vis[max_num] = 1; for(int j = 1; j <= n; j++){ if(!vis[j] && d[j] < min(p[max_num][j], d[max_num])){ d[j] = min(p[max_num][j], d[max_num]); } } } }*/ void spfa(int sec) { queue <int> q; for(int i = 1; i <= n; i++){ d[i] = -1; vis[i] = false; } d[sec] = inf; vis[sec] = true; q.push(sec); while(!q.empty()){ int v = q.front();q.pop(); vis[v] = false; for(int i = 1; i <= n; i++){ int t = min(d[v], p[v][i]); if(d[i] < t){ d[i] = t; if(!vis[i]){ vis[i] = true; q.push(i); } } } } } int main() { cin>>t; for(int cas = 1; cas <= t; cas++){ memset(p, 0, sizeof(p)); scanf("%d%d",&n,&m); for(int i = 0; i < m; i++){ int a, b, c; scanf("%d%d%d",&a,&b,&c); p[a][b] = c; p[b][a] = c; } spfa(1); cout<<"Scenario #"<<cas<<":\n"; cout<<d[n]<<endl<<endl; } return 0; } dijkstra的思路:做n-1次遍历 每次都找还没访问的节点中d[]最大的那个节点j【起点到这个节点的路径中 最小权值的边 比起点到其他节点的路径中最小权值的边的权值要大】
遍历这个结点的邻接点,做松弛操作
如果这个邻接点 i 没有被访问过 如果他此时的d比 j 的 d 和 j 到 i 的边的权值的最小值要小 那么就要更新 i 的d【让起点到 i 的路径经过 j】
spfa的思路:
设置一个队列 将起点加入队列 每次从队列中取出队头 更新剩余结点
松弛条件和dijkstra类似
给边权值初始化为0, 这样他的权值比所有的d都要小, 也就不会赋值给任何的d了
