1. 程式人生 > >圖論_最短路徑

圖論_最短路徑

分鐘 工作 矩陣 完成 tin struct int 算法 要求

Floyd算法:

用鄰接矩陣保存原圖,時間復雜度O(N^3),空間復雜度O(N^2),N為圖中節點個數。

一般情況下,被要求解圖的大小不超過200個結點,當圖使用鄰接矩陣表示時更為方便,否則要註意轉換。

因為算法完成後,圖中所有結點間的最短路徑都將被確定,所以其較適用於全源最短路徑長度問題。

for(int k=1;k<=n;k++){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(ans[i][k]==無窮||ans[k][j]==無窮) continue;
            
if(ans[i][j]==無窮||ans[i][k]+ans[k][j]<ans[i][j]) ans[i][j]=ans[i][k]+ans[k][j]; } } }

例5.5 最短路(1447)

題目描述:在每年的校賽裏,所有進入決賽的同學都會獲得一件很漂亮的t-shirt。但是每當我們的工作人員把上百件的衣服從商店運回到賽場的時候,卻是非常累的!所以現在他們想要尋找最短的從商店到賽場的路線,你可以幫助他們嗎?

輸入:輸入包括多組數據。每組數據第一行是兩個整數N、M(N<=100,M<=10000),N表示成都的大街上有幾個路口,標號為1的路口是商店所在地,標號為N的路口是賽場所在地,M則表示在成都有幾條路。N=M=0表示輸入結束。接下來M行,每行包括3個整數A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A與路口B之間有一條路,我們的工作人員需要C分鐘的時間走過這條路。輸入保證至少存在1條商店到賽場的路線。當輸入為兩個0時,輸入結束。

輸出:對於每組輸入,輸出一行,表示工作人員從商店走到賽場的最短時間。
樣例輸入:
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0
樣例輸出:
3
2
#include<stdio.h>
using namespace std;
int ans[101][101];
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0&&m==0) break;
        for(int i=1;i<=n;i++){
            
for(int j=1;j<=n;j++) ans[i][j]==-1; ans[i][i]=0; } while(m--){ int a,b,c; scanf("%d%d%d",&a,&b,&c); ans[a][b]=c; ans[b][a]=c; } for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(ans[i][k]==-1||ans[k][j]==-1) continue; if(ans[i][j]==-1||ans[i][k]+ans[k][j]<ans[i][j]) ans[i][j]=ans[i][k]+ans[k][j]; } } } printf("%d\n",ans[1][n]); } return 0; }

Dijkstra算法:

用鄰接鏈表或鄰接矩陣保存,只能求得某特定結點到其他所有結點的最短路徑長度,即單源最短路徑問題。

算法流程:

(1)初始化,集合K中加入結點1,結點1到結點1最短距離為0,到其他結點為無窮(或不確定)。

(2)遍歷與集合K中結點直接相鄰的邊(U,V,C),其中U屬於集合K,V不屬於集合K,計算由結點1出發按照已經得到的最短路到達U,再由U經過該邊到達V時的路徑長度。比較所有與集合K中結點直接相鄰的非集合K結點該路徑長度,其中路徑長度最小的結點被確定為下一個最短路徑確定的結點,其最短路徑長度即為這個路徑長度,最後將該結點加入集合K。

(3)若集合K中已經包含了所有的點,算法結束;否則重復步驟(2)。

下面重寫例4.5:

#include<stdio.h>
#include<vector>
using namespace std;
struct E{
    int next;
    int c;
};
vector<E> edge[101];
bool mark[101];
int Dis[101];
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0&&m==0) break;
        for(int i=1;i<=n;i++)
            edge[i].clear();
        while(m--){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            E tmp;
            tmp.c=c;
            tmp.next=b;
            edge[a].push_back(tmp);
            tmp.next=a;
            edge[b].push_back(tmp);
        }
        for(int i=1;i<=n;i++){
            mark[i]=false;
            Dis[i]=-1;
        }
        Dis[1]=0;
        mark[1]=true;
        int newP=1;
        for(int i=1;i<n;i++){
            for(int j=0;j<edge[newP].size();j++){//更新Dis 
                int t=edge[newP][j].next;
                int c=edge[newP][j].c;
                if(mark[t]) continue;
                if(Dis[t]>Dis[newP]+c||Dis[t]==-1)
                     Dis[t]=Dis[newP]+c;
            }
            int min=123123123;
            for(int j=1;j<=n;j++){//找newP 
                if(mark[j]) continue;
                if(Dis[j]==-1) continue;
                if(Dis[j]<min){
                    min=Dis[j];
                    newP=j;
                }
            } 
            mark[newP]=true;
        }
        printf("%d\n",Dis[n]);
    }
    return 0;
}

圖論_最短路徑