PAT 1003满分答案(25分)

先上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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值