1. 程式人生 > >圖的最短路徑Dijkstra

圖的最短路徑Dijkstra

dijk 找到 dfs ios aci count set float display

#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;
}

圖的最短路徑Dijkstra