圖論最短路問題和最小生成樹問題的區別


圖論最短路問題和最小生成樹問題的區別

區別:

一 區別
最小生成樹能夠保證整個拓撲圖的所有路徑之和最小,但不能保證任意兩點之間是最短路徑。
最短路徑是從一點出發,到達目的地的路徑最小。
圖論最短路問題——一個人的旅行
最小生成樹問題——Agri-Net

圖論最短路

包含dijkstra,spfa,Floyd
最短路dijkstra代碼:

//最短路——Dijkstra

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAX_V = 205;
int edge[MAX_V][MAX_V] ;
int dis[MAX_V];
bool vis[MAX_V];
int N,A,B;

void Dijkstra()
{
    int tmp,pos;
    memset(vis,false,sizeof(vis));
    for (int i = 1;i <= N;i++)
    {
       dis[i] = edge[A][i];   //從哪里開始尋找
    }
    dis[A] = 0;
    for (int i = 2;i <= N;i++)
    {
       tmp = INF;        //重新尋找
       for (int j = 1;j <= N;j++)
       {
           if (!vis[j] && tmp > dis[j])  //找到最小的權值
           {
              tmp = dis[j];
              pos = j;
           }
       }
       if (tmp == INF)   break; //沒有找的,直接進入下一個的尋找
       vis[pos] = true; //標記已經找過的點
       for (int j = 1;j <= N;j++)  //更新周圍的點的權值
       {
           if (dis[pos] + edge[pos][j] < dis[j])
           {
              dis[j] = dis[pos] + edge[pos][j];
           }
       }
    }
    printf("%d\n",dis[B] == INF?-1:dis[B]);
}


int main()
{
    while (~scanf("%d",&N) && N)
    {
       int tmp;
       for (int i = 0;i <= N;i++)
       {
           for (int j = 0;j <= i;j++)
           {
              if (i == j)   edge[i][j] = edge[j][i] = 0;
              else   edge[i][j] = edge[j][i] = INF;
           }
       }
       scanf("%d%d",&A,&B);
       for (int i = 1;i <= N;i++)
       {
           scanf("%d",&tmp);
           if (i - tmp > 0)
           {
              edge[i][i-tmp] = 1;
           }
           if (i + tmp <= N)
           {
              edge[i][i+tmp] = 1;
           }
       }
       Dijkstra();
    }
    return 0;
}
  

Floyd(不太理解)


for(k=1;k<=n;k++)   
  for(i=1;i<=n;i++)   
      for(j=1;j<=n;j++)   
 			if(e[i][j]>e[i][k]+e[k][j])   
     		e[i][j]=e[i][k]+e[k][j]; 

//實質就是動態規划


最小生成樹

一.kruskal算法
二.prim算法


**最小生成樹——prim算法**
 

/*計算最小生成樹的一種方法是使其連續地一步步長成。在每一步,都要把一個節點當做根並往上加邊,這樣也就把相關聯的頂點加到增長中的樹上。
在算法的任一時刻,我們都可以看到一個已經添加到樹上的頂點集,而其余頂點尚未加到這顆樹中。此時,算法在每一階段都可以選擇邊(u,v),使得(u,v)的值是所有u在樹上但v不在樹上的邊的值中的最小者,而找出一個新的頂點並把它添加到這棵樹中。圖指出該算法如何從v1開始構建最小生成樹。開始時,v1在構建中的樹上,它作為樹的根但沒有邊。每一步添加一邊和一個頂點到樹上。*/

int prim()
{
	memset(dis,INF,sizeof(dis));
	memset(vis,false,sizeof(vis));
	for (int i = 1;i <= N;i++)
	{
		dis[i] = edge[i][1];
	} 
	dis[1] = 0;
	vis[1] = true;
	int res = 0;
	for (int i = 1;i <= N - 1;i++)
	{
		int tmp = INF,pos;
		for (int j = 1;j <= N;j++)
		{
			if (!vis[j] && tmp > dis[j])
			{
				tmp = dis[j];
				pos = j;
			}
		}
		if (tmp == INF) return 0;
		vis[pos] = true;
		res += dis[pos];
		for (int j = 1;j <= N;j++)
		{
			if (!vis[j] && edge[pos][j] < dis[j]) //注意最短路與生成樹的更新條件很相似
			{
				dis[j] = edge[pos][j];
			}
		}
	}
	return res;
}




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM