图的最短路径问题,Bellman Ford算法,动态规划

1. 求有向无环图中节点s到节点t的最短路径

#include<iostream>
#include<vector>
#include<map>
#include<climits>
#include<iomanip>
using namespace std;

const int INF = INT_MAX/2;

// graph 
const int nodes = 6;
const int k = nodes - 1;

// define OPT
vector<int> OPT(nodes, INF);
map<int,int> next_node;

// 用于DAG,有向无环图,当有环时,会有循环依赖性,此算法无法解决循环依赖性问题,bellman_ford算法解决了循环依赖性问题
int shortest_path(vector< vector<int> > G, int start, int end);
int opt(vector< vector<int> > G, int v);

int main(){
    
    // define graph
    vector< vector<int> > G(nodes, vector<int>(nodes, INF));

    // graph 
    G[0][1] = 1;
    G[0][2] = 1;
    G[1][2] = 3;
    G[1][3] = 4;
    G[1][4] = 6;
    G[2][3] = 5;
    G[2][4] = 6;
    G[3][4] = 7;
    G[3][5] = 8;
    G[4][5] = 9;

    int start = 0, end = 5;
    int shortest_path_value = shortest_path(G, start, end);
    cout<<shortest_path_value<<endl;
    for(auto a:OPT) cout<<a<<" ";
    cout<<endl;

    for(int i=0; i<nodes; i++){
        if(i==end) continue;
        cout<<i<<"->";
        int count = 0;
        int curr_node = i;
        while( count++<nodes & next_node[curr_node]!=end){
            cout<<next_node[curr_node]<<"->";
            curr_node = next_node[curr_node];
        }
        cout<<end<<endl;
    }

    return 0;
}

int shortest_path(vector< vector<int> > G, int start, int end){
    OPT[end] = 0;
    opt(G,start);
    return OPT[start];
}

int opt(vector< vector<int> > G, int v){
    if(OPT[v]<INF){
        return OPT[v];
    }
    for(int w=0; w<nodes; w++){
        if(G[v][w]<INF){
            // OPT[v] = G[v][w] + opt(G,w) < OPT[v] ? G[v][w] + opt(G,w) : OPT[v];
            if(G[v][w] + opt(G,w) < OPT[v]){
                OPT[v] = G[v][w] + opt(G,w);
                next_node[v] = w;
            }
        }
    }
    return OPT[v];
}

 

2.任给一个图,求图中节点s到节点t不超过K步的最短路径,即Bellman Ford算法【1956,1958】

#include<iostream>
#include<vector>
#include<map>
#include<climits>
#include<iomanip>
using namespace std;

const int INF = INT_MAX/2;
// graph 1
// const int nodes = 6;
// graph 2
const int nodes = 5;

const int k = nodes - 1;
// define OPT
vector< vector<int> > OPT(nodes, vector<int>(nodes, INF));
map<int,int> next_node;
vector<int> path;

// 用于DAG,有向无环图, 但没有解决循环依赖性问题
int shortest_path(vector< vector<int> > G, int start, int end);
int opt(vector< vector<int> > G, int v);

// 解决了循环依赖性的问题
int bellman_ford(vector< vector<int> > G, int start, int end);
int min(vector< vector<int> > G, int i, int k, int start);

int main(){
    
    // define graph
    vector< vector<int> > G(nodes, vector<int>(nodes, INF));
    
    // graph 1
    // G[1][0] = -3;
    // G[1][2] = -4;
    // G[2][4] = -1;
    // G[2][5] = -2;
    // G[3][2] = 8;
    // G[3][0] = 3;
    // G[4][0] = 4;
    // G[4][1] = 6;
    // G[5][0] = 2;
    // G[5][3] = -3;

    // graph 2
    G[0][1] = 3;
    G[0][3] = 7;
    G[1][2] = 5;
    G[1][4] = 5;
    G[2][3] = 6;
    G[2][4] = 2;
    G[3][0] = 2;
    G[4][0] = 6;
    G[4][2] = 1;
    G[4][3] = 3;

    


    //bellman_ford algorithm
    int shortest_value = bellman_ford(G, 1, 0);
    cout<<shortest_value<<endl;
    for(auto x:OPT){
        for(auto a:x){
            if(a==INF){
                cout<<setw(4)<<right<<"-"<<" ";
            }else{
                cout<<setw(4)<<right<<a<<" ";
            }
        }
        cout<<endl;
    }
    
    for(auto a:next_node) cout<<a.first<<" : "<<a.second<<endl;
    for(int i=1; i<nodes; i++){
        cout<<i<<"->";
        int count = 0;
        int curr_node = i;
        while( count++<nodes & next_node[curr_node]!=0){
            cout<<next_node[curr_node]<<"->";
            curr_node = next_node[curr_node];
        }
        cout<<0<<endl;
    }
    return 0;
}

int bellman_ford(vector< vector<int> > G, int start, int end){
    for(int k=0; k<nodes; k++){
        OPT[end][k] = 0;
    }
    for(int k=1; k<nodes; k++){
        for(int v=1; v<nodes; v++){
            OPT[v][k] = min(G,v,k,start);
        }
    }
    return OPT[start][nodes-1];
}

int min(vector< vector<int> > G, int v, int k, int start){
    int min_val = OPT[v][k-1];
    int node = -1; // 选中的节点
    for(int w=0; w<nodes; w++){
        if(G[v][w]<INF){ // 节点v -> 节点w 存在一条边
            // min_val = (OPT[w][k-1] + G[v][w]) < min_val ? OPT[w][k-1] + G[v][w] : min_val;
            if( (OPT[w][k-1] + G[v][w]) < min_val ){
                min_val = OPT[w][k-1] + G[v][w];
                node = w;
                next_node[v] = w;
            }
        }
    }
    if(min_val>(INF/2)){
        min_val = OPT[v][k-1];
    }
    return min_val;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值