先上floyed算法
class Solution {
public://floyed算法
int networkDelayTime(vector<vector<int>>& times, int n, int k) {
vector<vector<int>>Directed_graph(n,vector<int>(n,INT_MAX));//初始化有向图
for(auto& x:times){
Directed_graph[x[0]-1][x[1]-1]=x[2];//原图是1,2,3,4 下标是0,1,2,3
}
for(int i=0;i<n;i++){
Directed_graph[i][i]=0;
}
for(int m=0;m<n;m++){//中转点从{1}增长到{1,2,3......n}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(Directed_graph[i][m]!=INT_MAX&&Directed_graph[m][j]!=INT_MAX)
Directed_graph[i][j]=min(Directed_graph[i][j],Directed_graph[i][m]+Directed_graph[m][j]);
}
}
}
int ans=INT_MIN;
for(int i=0;i<n;i++){
ans=max(ans,Directed_graph[k-1][i]);
}
return ans==INT_MAX?-1:ans;
}
};
FLOYED算法原理是从最小问题入手的动态规划,
首先最短路径的某一部分一定是最短路径(反证法可以证明),然后假设有一条最短路径p
如果最短路径p(从i边->j边),{1,2,3…k}这些节点包含这些路径,有两种情况
1.不包含k节点,i边到j边的最短路径被编号为{1,2…k-1}这些节点包含
2.如果包含k节点,呢么我们把路径p划分为 {i->k}和{k->j}然后由于最短路径的部分依然是最短路径,所以i->k的中间节点和k-j的中间节点一定被包含在{1,2…k-1}的节点中。
所以求i->j的最短路径被分解为寻求i->k的最短路径,k->j的最短路径
问题规模转换为{1,2,…k-1}
所以我们得到转移方程
Directed_graph[i][j]=min(Directed_graph[i][j],Directed_graph[i][m]+Directed_graph[m][j]);
这样递归下去我们就可以从简单的子问题入手,比如两个定点的直达边就是不经过k节点中转的最小路径,然后经过编号为{1}的节点中转的最短路径,直到经过在{1,2,…n}中的节点中转的最短路径,这个方法除了慢一点以外,充分体现了动态规划的思想。
Dijkstra算法 我们把算法运用在PAT1003上
#include<vector>
#include<iostream>
#include<utility>
#define INT_MAX 99999999
using namespace std;
int main(){
int city,road,start,end;
cin>>city>>road>>start>>end;
//cout<<"road: "<<road<<endl;
//cout<<"city: "<<city<<endl;
//cout<<"start: "<<start<<endl;
vector<vector<int>>undirected_graph(city,vector<int>(city,INT_MAX));
vector<int>resque_team(city,0),max_resque_team(city,0),nums(city,0);
for(int i=0;i<city;i++){
cin>>resque_team[i];
//cout<<resque_team[i]<<endl;
}
vector<int>dist(city,INT_MAX);
//初始化
dist[start]=0;
nums[start]=1;
max_resque_team[start]=resque_team[start];
for(int i=0;i<road;i++){
int a,b,c;//城市,边界,距离,构建一个无向图出来
cin>>a>>b>>c;
//cout<<a<<" "<<b<<" "<<c<<" "<<endl;
undirected_graph[a][b]=undirected_graph[b][a]=c;
}
vector<bool> visited(city,false);
for(int i=0;i<city;i++){
//选择最小边
int u=-1;int min=INT_MAX;
for(int j=0;j<city;j++){
if(visited[j]==false&&dist[j]<min){
u=j;min=dist[j];
//cout<<"minu: "<<u<<endl;
}
}
if(u==-1)break;//如果没有找到最小值并入路径,呢么跳出循环
visited[u]=true;//访问过了
for(int v=0;v<city;v++){
if(visited[v]==false&&undirected_graph[u][v]!=INT_MAX){
if(dist[v]>dist[u]+undirected_graph[u][v]){
dist[v]=dist[u]+undirected_graph[u][v];
nums[v]=nums[u];
max_resque_team[v]=resque_team[v]+max_resque_team[u];
}
else if(dist[v]==dist[u]+undirected_graph[u][v]){
nums[v]=nums[u]+nums[v];
if(max_resque_team[v]<max_resque_team[u]+resque_team[v]){
max_resque_team[v]=max_resque_team[u]+resque_team[v];
}
}
}
}
}
//cout<<undirected_graph[0][1]<<endl;
cout<<nums[end]<<" ";
cout<<max_resque_team[end]<<endl;
}