1. 程式人生 > >圖(最短路徑)1

圖(最短路徑)1

/*
題目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
*/
// floyd 時間複雜度 o(n^3) 空間複雜度o(n^2),n為結點個數
// floyd適用於圖的結點數<=200個,原圖需要轉換為鄰接矩陣表示
// 兩個結點間有多條邊時,選擇長度最小的邊,適用於全源最短路徑
#include <stdio.h>
int ans[101][101];//二維陣列,其初始值即為該圖的鄰接矩陣
int main(){
int n,m,i,j,k;
while(scanf("%d%d",&n,&m) != EOF){
if(n==0 && m==0) break;
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
ans[i][j] = -1;
//對鄰接矩陣初始化,我們用-1代表無窮
}
ans[i][i] = 0;//自己到自己的路徑長度設為0
}
while(m--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
ans[a][b] = ans[b][a] = c;
//對鄰接矩陣賦值,由於是無向圖,該賦值操作要進行兩次
}
for(k=1;k<=n;k++){//k從1到N迴圈,依次代表允許經過的中間結點編號小於等於k
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){//遍歷所有ans[i][j],判斷其值保持原值還是將要被更新
if(ans[i][k] == -1 || ans[k][j] == -1) continue;
//若兩值中有一個值為無窮,則ans[i][j]不能由於經過結點k而被更新,跳過迴圈,保持原值
if(ans[i][j] == -1 || ans[i][k]+ans[k][j]<ans[i][j])
ans[i][j]=ans[i][k]+ans[k][j];
//當由於經過k可以獲得更短的最短路徑時,更新該值
}
}

}
printf("%d\n",ans[1][n]);
}


return 0;

}

//dijkstra

#include <stdio.h>
#include <vector>
using namespace std;
struct E{//鄰接連結串列中的連結串列元素結構體
int next;//代表直接相鄰的結點
int c;//代表該邊的權值(長度)
};
vector<E> edge[101];//鄰接連結串列
bool mark[101];//標記,當mark[j]為true時表示結點j的最短路徑長度已經得到,該
//結點已經加入集合K
int dis[101];//距離向量,當mark[i]為true時,表示已得的最短路徑長度;否則,表示
//所有從結點1出發,經過已知的最短路徑達到集合K中的某結點,再經過一條邊到達結點
//i的路徑中最短的距離
int main(){
int n,m,i,j;
while(scanf("%d%d",&n,&m) != EOF){
if(n==0 && m==0) break;
for(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(i=1;i<=n;i++){//初始化
dis[i] = -1;//所有距離為-1,即不可達
mark[i] = false;//所有結點不屬於集合K
}
dis[1] = 0;//得到最近的點為結點1,長度為0
mark[1] = true;//將結點1加入集合K
int newp = 1;//集合K中新加入的點為結點1
for(i=1;i<n;i++){//迴圈n-1次,按照最短路徑遞增的順序確定其他n-1個點
//的最短路徑長度
for(j=0;j<edge[newp].size();j++){
//遍歷與該新加入集合K中的結點直接相鄰的邊
int t = edge[newp][j].next;//該邊的另一個結點
int c = edge[newp][j].c;//該邊的長度
if(mark[t] == true) continue;//若另一個結點也屬於集合K,則跳過
if(dis[t] == -1 || dis[t] > dis[newp]+c)
//若該結點尚不可達,或者該結點從新加入的結點經過一條邊到達時比以往距離更短
dis[t] = dis[newp] + c;//更新其距離資訊
}
int min = 123123123;//最小值初始化為一個大整數,為找最小值做準備
for(j=1;j<=n;j++){//遍歷所有結點
if(mark[j] == true) continue;//若其屬於集合K則跳過
if(dis[j] == -1) continue;//若該結點仍不可達則跳過
if(dis[j] < min){//若該結點經由結點1至集合K中的某點在經過一條
//邊到達時距離小於當前最小值
min = dis[j];//更新其為最小值
newp = j;//新加入的點暫定為該點
}
}
mark[newp] = true;//將新加入的點加入集合K,dis[newp]雖然數值不變,
//但意義發生變化,由所有經過集合K中的結點再經過一條邊到達時的距離中
//的最小值 變為 從結點1到結點newp 的最短距離

}
printf("%d\n",dis[n]);//輸出
}
return 0;
}

相關推薦

路徑1

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

資料結構——帶權有向路徑演算法Dijkstra演算法

Dijkstra演算法是由荷蘭電腦科學家艾茲格·迪科斯徹發現的。演算法解決的是有向圖中最短路徑問題。 舉例來說,如果圖中的頂點表示城市,而邊上的權重表示著城市間開車行經的距離。 Dijkstra演算法可以用來找到兩個城市之間的最短路徑。 Dijkstra演算法的輸入包含了一個有權重的有向圖G,以及G中的一個

【資料結構】路徑Dijkstra演算法的JAVA程式碼實現

最短路徑的概念最短路徑的問題是比較典型的應用問題。在圖中,確定了起始點和終點之後,一般情況下都可以有很多條路徑來連線兩者。而邊或弧的權值最小的那一條路徑就稱為兩點之間的最短路徑,路徑上的第一個頂點為源點,最後一個頂點為終點。圖的最短路徑的演算法有很多,本文主要介紹狄克斯特拉(

hdu 2544路徑

cst cstring while span code 最短路徑 bre sha nbsp 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #inclu

1072 Gas Station 30 分路徑

  #include<bits/stdc++.h> using namespace std; const int N=1e3+100; int n,m,k,Ds; int mp[N][N]; int dis[N]; int vis[N]; int inf=0x3f3f3f3

Floyd 演算法路徑

基本思想:  1,從任意一條單邊路徑開始。所有兩點之間的距離是邊的權,如果兩點之間沒有邊相連,則權為無窮大。 2,對於每一對頂點 u 和 v,看看是否存在一個頂點 w 使得從 u 到 w 再到 v 比已知的路徑更短。如果是更新它。 時間複雜度:O() 參考:弗洛伊德(Flo

Dijkstra--簡易版 路徑

Dijkstra演算法思路: G={V,E} 1. 初始時令 S={V0},T=V-S={其餘頂點},T中頂點對應的距離值 若存在<V0,Vi>,d(V0,Vi)為<V0,Vi>弧上的權值 若不存在<V0,Vi>,d(V0,Vi)為∞ 2. 從

Floyd演算法與Dijkstra演算法路徑

#include <iostream> #include <cstdio> #include <vector> using namespace std; int Dis[101]; bool mark[101]; struct E { int next; i

路徑規劃路徑演算法C#實現

    ///<summary>/// RoutePlanner 提供圖演算法中常用的路徑規劃功能。     /// 2005.09.06     ///</summary>publicclass RoutePlanner     {         public RoutePlan

Dijkstra演算法路徑

基本思想 每次找到離源點最近的一個頂點,然後以該頂點為中心進行擴充套件,最終得到源點到其餘所有點的最短路徑。 基本歩驟 將所有頂點分為兩部分:已知最短路徑的頂點集合P和未知最短路徑的頂點集合Q。最開始,已知最短路徑的頂點集合P中只有源點

uva658路徑+隱式+狀態壓縮

匹配 define top har 讀者 還記得 題意 priority 節點 題目連接(vj):https://vjudge.net/problem/UVA-658 題意:補丁在修正 bug 時,有時也會引入新的 bug。假定有 n(n≤20)個潛在 bug 和 m(m≤

弗洛伊德Floyd演算法求路徑

https://blog.csdn.net/jeffleo/article/details/53349825 弗洛伊德基本思想 弗洛伊德演算法作為求最短路徑的經典演算法,其演算法實現相比迪傑斯特拉等演算法是非常優雅的,可讀性和理解都非常好。 基本思想: 弗洛伊德演算法定義了兩個二維

程式設計基礎31 tips 路徑

1072 Gas Station (30 分) A gas station has to be built at such a location that the minimum distance between the station and any of the residential ho

程式設計基礎30 tips 路徑

1018 Public Bike Management (30 分) There is a public bike service in Hangzhou City which provides great convenience to the tourists from all over th

程式設計基礎29 路徑

1003 Emergency (25 分) As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cit

Java使用Jgrapht,求無向有向加權路徑

把有向圖相鄰頂點之間新增方向相反的兩條邊相當於無向圖 先上程式碼,後面有空再添加註釋 根據文末圖4.2對應的例題,可以驗證程式結果           1 package com.sun.GraphTheoryRepor

【loj】#10064. 「一本通 3.11」黑暗城堡路徑生成樹 dijkstra+Prim

題目描述: 你知道黑暗城堡有 N個房間,M 條可以製造的雙向通道,以及每條通道的長度。 城堡是樹形的並且滿足下面的條件: 設 Di​ 為如果所有的通道都被修建,第 i 號房間與第 1 號房間的最短路徑長度; 而 Si​ 為實際修建的樹形城堡中第 i 號房間與第 1 號房間的路徑長度;

利用graphviz來實現無向視覺化路徑

1.首先下載graphviz,並安裝。 2.將輸入的邊儲存起來。 3.將最短路徑求出,並存儲每個頂點的前驅。 4.在程式中將建邊的程式碼寫入一個dot檔案中。 5.將dot檔案轉化為.png形式。 6.利用system函式開啟.png。 程式碼如下: #include &

1018 Public Bike Management 30 分的遍歷and路徑

    這題不能直接在Dijkstra中寫這個第一 標尺和第二標尺的要求 因為這是需要完整路徑以後才能計算的  所以寫完後可以在遍歷   #include<bits/stdc++.h> using namespace std; int c

無向的Dijkstra演算法求任意一對頂點間的路徑迪傑斯特拉演算法

public class Main{ public static int dijkstra(int[][] w1,int start,int end) { boolean[] isLable = new boolean[w1[0].length];//是否標上所有的號 i