图的最短路径Dijkstra

#include <stdio.h>
#include <string.h> 
#include <vector>
#include <queue>
#include <iostream> 
using namespace std;

const int MAXV = 1000;
const int INF = 1000000000; 

struct Node
{
    int v,dis;    
};

vector<Node> Adj[MAXV];

int n;//n为顶点数,图G使用邻接表实现,MAXV为最大顶点数(点数决定如何遍历边)
int m;// 边数(决定输入什么样的图) 
int s;//起点
 
int d[MAXV];//起点到达各个点的最短路径长度
bool vis[MAXV] = {false};//标记数组,vis[i]==true表示已访问,初值均为false

int pre[MAXV]={0}; //记录到某一个点的前驱 

void Dijkstra(int s)
{
    fill(d,d+MAXV,INF);
    d[s] = 0;//起点s到达自身的距离为0
    
    //遍历所有的点 
    for(int i=0;i<n;i++)
    {
        //u为使得d[u]最小的点,MIN存放该最小的d[u] 
        int u = -1,MIN = INF;
        //每一趟找一个已连通的最短路径的点出来 
        for(int j=0;j<n;j++)
        {
            
            if(vis[j] == false && d[j] < MIN)
            {
                u = j;
                MIN = d[j];
            }
         } 
         
         //找不到小于INF的d[u],说明剩下的顶点和起点s不连通 
         if(u == -1)
         {
             return;
         }
         //找到了 
         else
         {
             vis[u] = true;//找到则标记成已访问,每一趟可以确定一个最短点
             
             //遍历u能到达的所有顶点v,并判断以u为中转到j的距离是否比原来的小,如果小则更新 
            for(int j=0;j < Adj[u].size();j++)
            {
                
                int v = Adj[u][j].v;
                
                //以当前最短路径的点为中转,看看是否比原来的距离小 ,如果小,则优化d[v] 
                if(vis[v] == false && d[u] + Adj[u][j].dis < d[v])
                {
                    d[v] = d[u] + Adj[u][j].dis;
                    
                    //记录前驱
                    pre[v] = u; 
                 } 
             } 
         } 
     } 
 } 
 
 //输出从起点到v的最短路径 
 void print(int s,int v)
 {
     if(v == s)
     {
         cout << s << endl;
         return;
     }
     
     print(s,pre[v]);
     cout<< v << endl;
 } 

int main()
{
    //顶点个数,边数,起点编号 
    cin >> n >> m >> s;
    
    int u,v,w;
    Node tmp;
    for (int i=0;i<m;i++)
    {
        cin >> u >> v >> w;
        tmp.v = v;
        tmp.dis = w;
        Adj[u].push_back(tmp);
    }
    
    Dijkstra(s);
    
    for(int i=0;i<n;i++)
    {
        cout << d[i] << " ";
    }

    cout << endl;
    print(0,5);
    return 0;
    
}

练习: PAT A1030 Travel Plan

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;

const int MAXV = 510;
const int INF = 1000000000;

//n为点数,m为边数,st和ed分别为起点和终点
//G为邻接矩阵,weight为点权 
//d[]记录最短距离,w[]记录最大点权之和
int n,m,st,ed,G[MAXV][MAXV],weight[MAXV]; 
int d[MAXV],w[MAXV];
//vis[i] == true 表示顶点i已访问 
bool vis[MAXV] = {false}; 

vector<int> pre[MAXV];

void Dijkstra(int s)
{
    fill(d,d+MAXV,INF);
    d[s] = 0;
    
    //每次找出一个最短的点,一共找n个 ,最短的点就是在最短路径中的点,设置为访问 
    for(int i=0;i<n;i++)
    {
        int u = -1,MIN = INF;
        //找最短的点 
        for(int j=0;j<n;j++)
        {
            if(vis[j] == false && d[j] < MIN)
            {
                u = j;
                MIN = d[j];
            }
        }
        
        if(u == -1 ) return;
        vis[u] = true;
        
        //看u能到哪些点 ,并以u为中转,更新其他距离 
        //以u为中转,到v 
        for(int v=0;v<n;v++) 
        {
            if(vis[v] == false && G[u][v] != INF)
            {
                if(d[u] + G[u][v] < d[v])
                {
                    d[v] = d[u] + G[u][v];
                    pre[v].clear();
                    //令v的前驱为u 
                    pre[v].push_back(u); 
                }
                else if(d[u]+G[u][v] == d[v])
                {
                    pre[v].push_back(u);
                 } 
             } 
        } 
    }
}

//求最大值
int optvalue = -INF; 
//最优路径及临时路径 
vector<int> path,tempPath;
//路径数+1 
int totalCount = 0;

void DFS(int v)
{
    
    //    cout << endl;
    //到达叶子节点,即起点 
    if(v == st)
    {
        totalCount++;
        tempPath.push_back(v);
        int value = 0;
        for(int i=0;i<tempPath.size();i++)
        {
//            value = value + G[ tempPath[i] ][ tempPath[i+1] ];
            value = value + weight[tempPath[i]];
         } 
         
         if(value > optvalue)
         {
             optvalue = value;
             path = tempPath;
         }
         
         //回溯
         tempPath.pop_back();
         return; 
    } 
    //将当期访问的点加入临时路径 
    tempPath.push_back(v);
    //访问所有前驱 
    for(int i=0;i<pre[v].size();i++)
    {
        //递归遍历所有前驱 
        DFS(pre[v][i]);
    }
    tempPath.pop_back(); 
 } 

int main()
{
    cin >> n >> m >> st >> ed;
    for(int i=0;i<n;i++)
    {
        cin >> weight[i];
    }
    
    int u,v;
    fill(G[0],G[0] + MAXV * MAXV,INF);
    
    for(int i=0;i<m;i++)
    {
        cin >> u >> v;
        cin >> G[u][v];
        G[v][u] = G[u][v];
     } 
    
    Dijkstra(st);
    
    
    DFS(ed);
    
    cout << totalCount << " " << optvalue << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xiaochi/p/10409972.html