資料結構------最短路徑Dijkstra和最小生成樹Prim

壞牧羊人.發表於2020-11-30

prim和Dijkstra演算法主要是在d陣列上面的含義不同,對於prim的d陣列是d[i]是i節點到最小生成樹結合的距離,而Dijkstra的d陣列則是i節點到目標節點s的距離。

最短路徑並用path並查集陣列來記錄路徑節點資訊

#include <bits/stdc++.h>
#define maxv 1000
#define INF 99999
using namespace std;
int n,m,s;/*n個頂點、m條邊、s為起點*/
int path[maxv];/*一個並查集陣列*/
int G[maxv][maxv];
int d[maxv];/*d[i]代表著第i個節點到目標節點s的距離*/
bool  vis[maxv]={false};
int findfater(int x){
    int index=x;
    int temp[100];
    int top=0;
    temp[top++]=x;
     while(path[x]!=x){
           //cout<<x<<' ';
           x=path[x];
           temp[top++]=x;
     }
     //temp[top++]=x;
     for(int i=top-1;i>=0;i--){
        if(d[index]==INF){
            cout<<s<<"  不可達  "<<i;
            break;
        }
        else if(d[index]==0){
             cout<<"自身節點";
             break;
        }
        if(i!=0){
            cout<<temp[i]<<"-->";
        }else{
            cout<<temp[i]<<"\t\t路徑長度為"<<d[index];
        }
     }
     cout<<endl;
}
int initpath(int n){
    for(int i=0;i<n;i++){
          path[i]=i;
    }
}
void InitG(){
   for(int i=0;i<maxv;i++){
      for(int j=0;j<maxv;j++){
            G[i][j]=INF;
      }
   }
}
/*m為目標節點*/
void  Dijkstra(int s,int n){
   initpath(n);
   //path[s]=s;//並查集初始化
   fill(d,d+maxv,INF);
   d[s]=0;
   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;
        for(int v=0;v<n;v++){
            if(vis[v]==false&&G[u][v]!=INF&&G[u][v]+d[u]<d[v]){
                  d[v]=G[u][v]+d[u];
                  path[v]=u;
            }
        }
   }
}
int main()
{

     cout<<"請輸入頂點數和邊數:"<<endl;
     cin>>n>>m>>s;
     int u,v,weight;
     InitG();/*初始化全部為INF*/
     for(int i=0;i<m;i++){
          cin>>u>>v>>weight;
          if(weight<G[u][v]){/*防止這個兩個頂點之間存在多條邊*/
                G[u][v]=weight;
          }
     }
    Dijkstra(s,n);
    for(int i=0;i<n;i++){
        findfater(i);
    }

    return 0;
}
/*6個頂點 8條邊 以0號節點為例子
6 8 1
0 1 1
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3
0 1 5 3 4 6
*/

Prim演算法

#include <bits/stdc++.h>
#define maxv 1000
#define INF 99999
using namespace std;
int G[maxv][maxv];
int d[maxv];/*d[i]代表著第i個節點到結合S的距離*/
bool  vis[maxv]={false};
void InitG(){
   for(int i=0;i<maxv;i++){
      for(int j=0;j<maxv;j++){
            G[i][j]=INF;
      }
   }

}
int prim(int n){
   int ans=0;
   fill(d,d+maxv,INF);
   d[0]=0;
   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 -1;
        }
        vis[u]=true;
        ans+=d[u];
        for(int v=0;v<n;v++){
            if(vis[v]==false&&G[u][v]!=INF&&G[u][v]<d[v]){
                  d[v]=G[u][v];
            }
        }
   }
   return ans;

}
int main()
{
     int n,m;
     cout<<"請輸入頂點數和邊數:"<<endl;
     cin>>n>>m;
     int u,v,weight;
     InitG();/*初始化全部為INF*/
     for(int i=0;i<m;i++){
          cin>>u>>v>>weight;
          if(weight<G[u][v]){
                G[v][u]=G[u][v]=weight;
          }
     }
    cout<<prim(n);
    return 0;
}
/*
6 10
0 1 4
0 4 1
0 5 2
1 2 6
1 5 3
2 3 6
2 5 5
3 4 4
3 5 5
4 5 3
結果為15
*/

相關文章