1. 程式人生 > >【資料結構】所有頂點對的最短路徑 Floyd演算法

【資料結構】所有頂點對的最短路徑 Floyd演算法

所有頂點對的最短路徑問題是指:對於給定的有向圖G=(V,E),求任意一對頂點之間的最短路徑。

可以求解得到的 A_{k+1}[i][j] 的遞推公式:

A_{-1}[i][j]=g.edges[i][j]

A_{k+1}[i][j]=min\begin{Bmatrix} A_{k}[i][j],A_{k}[i][k+1]+A_{k}[k+1][j] \end{Bmatrix}

#include <stdio.h>
#include <stdlib.h>
const int FINITY = 5000;
const int M = 20;
typedef struct 
{
	char vex[M];
	int edges[M][M];
	int e,n;
}Mgraph;

int dist[M][M];
int path[M][M];

void creat (Mgraph *g,int c)
{
	int i,j,k,w;
	FILE *f;
	f=fopen("test.txt","r");
	if(f)
	{
		fscanf(f,"%d%d",&g->n,&g->e);
		for(i=0;i<g->n;i++)
			fscanf(f,"%1s",&g->vex[i]);
		for(i=0;i<g->n;i++)
		{
			for(j=0;j<g->n;j++)
			{
				if(i==j)	g->edges[i][j]=0;
				else	g->edges[i][j]=FINITY;
			}
		}
		for(k=0;k<g->e;k++)
		{
			fscanf(f,"%d%d%d",&i,&j,&w);
			g->edges[i][j]=w;
			if(c==0)	g->edges[j][i]=w;
		}
		fclose(f);
	}
	else
	{
		g->n=0;
	}
}

void print(Mgraph g)
{
	int i,j;
	printf("%一共有%d個結點,%d條邊\n",g.n,g.e);
	for(i=0;i<g.n;i++)
	{
		for(j=0;j<g.n;j++)
		{
			printf("%-6d",g.edges[i][j]);
		}
		printf("\n");
	}
}

void floyd(Mgraph g)
{
	int i,j,k;
	for(i=0;i<g.n;i++)//初始化
	{
		for(j=0;j<g.n;j++)
		{
			dist[i][j]=g.edges[i][j];
			if(i!=j && dist[i][j]<FINITY)
			{
				path[i][j]=i;
			}
			else
			{
				path[i][j]=-1;
			}
		}
	}
	for(k=0;k<g.n;k++)
	{
		for(i=0;i<g.n;i++)
		{
			for(j=0;j<g.n;j++)
			{
				if(dist[i][j]>(dist[i][k]+dist[k][j]))
				{
					dist[i][j]=dist[i][k]+dist[k][j];
					path[i][j]=k;
				}
			}
		}
	}
}

void find(Mgraph g)
{
	int a,b;
	int x;
	while(1)
	{
		printf("\n請輸入有向圖中的任意兩個頂點的序號:");
		scanf("%d%d",&a,&b);
		if(a<0 || a>=g.n || b<0 || b>=g.n)
		{
			printf("頂點序號輸入有誤,請重新輸入!!\n");
			continue;
		}
		printf("%c 和 %c 的最短路徑長度是 %d\n",g.vex[a],g.vex[b],dist[a][b]);
		printf("是否繼續?(1/0)\n請輸入:");
		scanf("%d",&x);
		if(x!=1)
		{
			exit(0);
		}
	}
}

int main ()
{
	Mgraph g;
	creat(&g,1);
	print(g);
	floyd(g);
	find(g);
	printf("程式結束\n");
	return 0;
}