求最短路徑(迪杰斯特拉算法鲤屡,弗洛伊德算法)

迪杰斯特拉算法

從某個頂點到其余各頂點的最短路徑(? o(n的平方))

舉個例子:

問題:求出下圖中頂點1到其余各頂點的最短路徑

題目1
DIST

這個圖的計算方法,

比如s是1的時候列粪,DIST就是1到各個頂點的最短距離审磁,不能到達就是無窮,可以確定最短的是1->5

然后岂座,s就是1,5,DIST就是從5到其他頂點的距離+上圖1->5的距離态蒂,和1時候的DIST對比,比他小填入就可以了费什,否則填上面的

...其他類似

從圖中可以看出頂點1到其他頂點的最短路徑依次是20,31,28,10,17,25,35,按迪杰斯特拉算法所選頂點依次是5,6,2,7,4,3,8

代碼:

#include <iostream>

using namespace std;

int main(){

? ? int m,n;//m是有多少個頂點钾恢,n是從哪個頂點開始

? ? cin>>m>>n;

? ? int p[m][m];

? ? for(int i=0;i<m;i++){

? ? ? ? for(int j=0;j<m;j++){

? ? ? ? ? ? cin>>p[i][j];

? ? ? ? }

? ? }

? ? int d[m];//用來存儲n頂點到其他頂點的最短路徑,輸出從1到m-1的數(shù),默認(rèn)是0

? ? for(int i=0;i<m;i++){

? ? ? ? d[i]=0;

? ? }

? ? //要想得到其他最短路徑瘩蚪,需要循環(huán)m-1次泉懦,每次確定一個最短路徑

? ? int k=m-1;

? ? int v[m];//看是否已經(jīng)確定是最短路徑了,初始化為0如果是1標(biāo)識確定了

? ? for(int i=0;i<m;i++){

? ? ? ? v[i]=0;

? ? }

? ? int p1=n;

? ? int min;

? ? int min_i;

? ? bool b=true;

? ? for(int i=0;i<m;i++){

? ? ? ? if(i==n){

? ? ? ? ? ? continue;

? ? ? ? }

? ? ? ? if(p[n][i]!=0&&b){//找到第一個非0的元素標(biāo)識為最小的

? ? ? ? ? ? min=p[n][i];

? ? ? ? ? ? min_i=i;

? ? ? ? ? ? b=false;

? ? ? ? ? ? d[i]=p[n][i];

? ? ? ? }

? ? ? ? if(!b&&p[n][i]!=0){

? ? ? ? ? ? if(p[n][i]<min){

? ? ? ? ? ? ? ? min=p[n][i];

? ? ? ? ? ? ? ? min_i=i;

? ? ? ? ? ? }

? ? ? ? ? ? d[i]=p[n][i];

? ? ? ? }

? ? }

? ? v[min_i]=1;//標(biāo)識確定了最短路徑的下標(biāo)

? ? n=min_i;//有最小的從最小的那個開始疹瘦,和上一次的d[i]對比崩哩,看是否有比他小的

? ? k=k-1;

? ? for(int i=0;i<m;i++){

? ? ? ? cout<<d[i]<<" ";

? ? }

? ? cout<<n<<endl;

? ? while(k--){//進行m-1次遍歷,確定最小

? ? ? ? for(int i=0;i<m;i++){

? ? ? ? ? ? if(v[i]==1||i==p1){

? ? ? ? ? ? ? ? continue;

? ? ? ? ? ? }

? ? ? ? ? ? if(p[n][i]!=0&&d[i]!=0){

? ? ? ? ? ? ? ? if(p[n][i]+d[min_i]<d[i]){

? ? ? ? ? ? ? ? ? ? d[i]=p[n][i]+d[min_i];

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? if(p[n][i]!=0&&d[i]==0){

? ? ? ? ? ? ? ? d[i]=p[n][i]+d[min_i];

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? b=true;

? ? ? ? //確定d[i]不為0的最小下標(biāo)并且v[i]==0的下標(biāo)

? ? ? ? for(int i=0;i<m;i++){

? ? ? ? ? ? if(d[i]!=0&&b&&v[i]==0){//找到第一個非0的元素標(biāo)識為最小的

? ? ? ? ? ? ? ? min=d[i];

? ? ? ? ? ? ? ? min_i=i;

? ? ? ? ? ? ? ? b=false;

? ? ? ? ? ? }

? ? ? ? ? ? if(!b&&d[i]!=0&&v[i]==0){

? ? ? ? ? ? ? ? if(d[i]<min){

? ? ? ? ? ? ? ? ? ? min=d[i];

? ? ? ? ? ? ? ? ? ? min_i=i;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? v[min_i]=1;

? ? ? ? n=min_i;

? ? ? ? for(int i=0;i<m;i++){

? ? ? ? ? ? cout<<d[i]<<" ";

? ? ? ? }

? ? ? ? cout<<n<<endl;

? ? }

? ? for(int i=0;i<m;i++){

? ? ? ? if(i!=p1){

? ? ? ? ? ? if(d[i]==0){

? ? ? ? ? ? ? ? cout<<-1<<" ";

? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? cout<<d[i]<<" ";

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? return 0;

}

結(jié)果:

結(jié)果1

弗洛伊德算法

各個頂點之間的最短距離

舉例:

有一個帶權(quán)有向圖言沐,用弗洛伊德算法求各頂點間的最短距離的矩陣序列A1,A2,A3

題目2

每一對頂點之間的路徑邓嘹,初始用A(-1)標(biāo)識:

A(-1)

求A(0),A(1),A(2),

A(0)在A(-1)的基礎(chǔ)上求A[i][0]+A[0][j]<A[i][j]

比較好使不易出錯的方法:先找出第0列的元素,然后找出第0行的元素险胰,然后加起來汹押,構(gòu)造一個新的矩陣,這個矩陣和A(-1)矩陣比較起便,找出其中比A(-1)矩陣中的元素小的棚贾,然后代替A(-1)中的元素,就是A(0)矩陣了

A(1)在A(0)的基礎(chǔ)上

A(2)在A(1)的基礎(chǔ)上

A(0)
A(1)
A(2)

代碼:

#include <iostream>

using namespace std;

int main(){

? ? int n;

? ? cin>>n;

? ? int p[n][n];

? ? int v[n][n];//=1就是無窮

? ? for(int i=0;i<n;i++){

? ? ? ? for(int j=0;j<n;j++){

? ? ? ? ? ? cin>>p[i][j];

? ? ? ? ? ? if(p[i][j]==0&&i!=j){

? ? ? ? ? ? ? ? v[i][j]=1;

? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? v[i][j]=0;

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? int m=n;

? ? int k=0;

? ? while(m--){

? ? ? ? int temp[n][n];//臨時數(shù)組

? ? ? ? for(int i=0;i<n;i++){

? ? ? ? ? ? for(int j=0;j<n;j++){

? ? ? ? ? ? ? ? if(v[k][j]==1||i==j||v[i][k]==1){//如果是無窮,或者是對角線上的值

? ? ? ? ? ? ? ? ? ? temp[i][j]=p[i][j];

? ? ? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? ? ? temp[i][j]=p[k][j]+p[i][k];

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? k++;

//? ? ? ? cout<<"temp數(shù)組:"<<endl;

//? ? ? ? for(int i=0;i<n;i++){

//? ? ? ? ? ? for(int j=0;j<n;j++){

//? ? ? ? ? ? ? ? cout<<temp[i][j]<<" ";

//? ? ? ? ? ? }

//? ? ? ? ? ? cout<<endl;

//? ? ? ? }

//? ? ? ? cout<<endl;

? ? ? ? for(int i=0;i<n;i++){

? ? ? ? ? ? for(int j=0;j<n;j++){

? ? ? ? ? ? ? ? if(i==j){

? ? ? ? ? ? ? ? ? ? continue;

? ? ? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? ? ? if(v[i][j]==1){//是無窮

? ? ? ? ? ? ? ? ? ? ? ? p[i][j]=temp[i][j];

? ? ? ? ? ? ? ? ? ? ? ? if(p[i][j]!=0){

? ? ? ? ? ? ? ? ? ? ? ? ? ? v[i][j]=0;

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? }else{//不是無窮

? ? ? ? ? ? ? ? ? ? ? ? if(temp[i][j]<p[i][j]){

? ? ? ? ? ? ? ? ? ? ? ? ? ? p[i][j]=temp[i][j];

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

//? ? ? ? cout<<" p數(shù)組"<<endl;

//? ? ? ? for(int i=0;i<n;i++){

//? ? ? ? ? ? for(int j=0;j<n;j++){

//? ? ? ? ? ? ? ? cout<<p[i][j]<<" ";

//? ? ? ? ? ? }

//? ? ? ? ? ? cout<<endl;

//? ? ? ? }

? ? }

? ? for(int i=0;i<n;i++){

? ? ? ? for(int j=0;j<n;j++){

? ? ? ? ? ? if(i==j){

? ? ? ? ? ? ? ? cout<<p[i][j]<<" ";

? ? ? ? ? ? ? ? continue;

? ? ? ? ? ? }else if(p[i][j]==0){

? ? ? ? ? ? ? ? p[i][j]=-1;

? ? ? ? ? ? }

? ? ? ? ? ? cout<<p[i][j]<<" ";

? ? ? ? }

? ? ? ? cout<<endl;

? ? }

? ? return 0;

}

結(jié)果:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末榆综,一起剝皮案震驚了整個濱河市鸟悴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奖年,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沛贪,死亡現(xiàn)場離奇詭異陋守,居然都是意外死亡,警方通過查閱死者的電腦和手機利赋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門水评,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人媚送,你說我怎么就攤上這事中燥。” “怎么了塘偎?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵疗涉,是天一觀的道長。 經(jīng)常有香客問我吟秩,道長咱扣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任涵防,我火速辦了婚禮闹伪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己偏瓤,他們只是感情好杀怠,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著厅克,像睡著了一般赔退。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上已骇,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天离钝,我揣著相機與錄音,去河邊找鬼褪储。 笑死卵渴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鲤竹。 我是一名探鬼主播浪读,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辛藻!你這毒婦竟也來了碘橘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吱肌,失蹤者是張志新(化名)和其女友劉穎痘拆,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體氮墨,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡纺蛆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了规揪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桥氏。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖猛铅,靈堂內(nèi)的尸體忽然破棺而出字支,到底是詐尸還是另有隱情,我是刑警寧澤奸忽,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布堕伪,位于F島的核電站,受9級特大地震影響栗菜,放射性物質(zhì)發(fā)生泄漏刃跛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一苛萎、第九天 我趴在偏房一處隱蔽的房頂上張望桨昙。 院中可真熱鬧检号,春花似錦、人聲如沸蛙酪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桂塞。三九已至凹蜂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阁危,已是汗流浹背玛痊。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留狂打,地道東北人擂煞。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像趴乡,于是被迫代替她去往敵國和親对省。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容