问题
给定一定无负值圈的图G,顶点集为V,使用Dijkstra算法求出G中顶点n到顶点m的最短路径,使用Floyd算法求出多源的最短路径,具体的图如下
代码
Dijkstra算法(单源最短路径),所谓单源是在一个有向图中,从一个顶点出发,求该顶点至所有可到达顶点的最短路径问题。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Node{//定义结点
int index;
int value;
struct Node* next;
}Node;
typedef struct Graph{//定义图
int vertex;
int edge;
Node con[100];
}Graph;
typedef struct Edge{//定义边集
int head;
int rear;
int value;
}Edge;
typedef struct DijkstraPoint{//定义迪杰斯特拉算法的point
int value;
int path;
int flag;
}DijkstraPoint;
Graph init(){
Graph MyGraph;
int v,e,head,rear,value;
memset(MyGraph.con, 0, sizeof(Node) * 100);
scanf("%d %d", &v, &e);//输入边和点的数量
MyGraph.edge = e;
MyGraph.vertex = v;
for (int i = 0; i < v; i++)
MyGraph.con[i].next = NULL;
for (int i = 0; i < e; i++){
scanf("%d %d %d",&head,&rear,&value);
Node* tmp1 = (Node*)malloc(sizeof(Node));
tmp1->index = rear;
tmp1->value = value;
tmp1->next = MyGraph.con[head].next;
MyGraph.con[head].next = tmp1;
}
return MyGraph;
}
void Dijkstra(Graph G){
DijkstraPoint dist[100];//创建dist数组用来存储第一个顶点到其余顶点的最短距离
int start;
for (int i = 0; i < G.vertex; i++){
dist[i].path=0;
dist[i].value= 999999999;//视为无穷大
dist[i].flag = 0;
}
scanf("%d", &start);
dist[start].value = 0;
while (1)
{
int min =999999999;
int Vmin = 0;
for (int i = 0; i < G.vertex; i++)
{
if (dist[i].flag == 0 && dist[i].value < min)
{
min = dist[i].value;
Vmin = i;
}
}
if (min == 999999999)
break;
else
dist[Vmin].flag = 1;
for (Node* tmp = G.con[Vmin].next; tmp != NULL; tmp = tmp->next)
{
if(dist[tmp->index].flag == 0)
if (dist[Vmin].value + tmp->value < dist[tmp->index].value)
{
dist[tmp->index].value = dist[Vmin].value + tmp->value;
dist[tmp->index].path = Vmin;
}
}
}
for (int i=G.vertex-1;i>=0;i--)
{
if (i!=start)
{
printf(" %d到%d的最短路径:\n", start, i);
int tmp = i;
while (tmp != start)
{
printf("%d<-", tmp);
tmp = dist[tmp].path;
}
printf("%d\n",start);
}
}
}
int main(){
Graph G;
G=init();
Dijkstra(G);
Floyd算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或有向图或负权(无负权回路)的最短路径问题。
#include<stdio.h>
#include<string.h>
#define NUMS 12
typedef struct{
char vertex[NUMS];
int edges[NUMS][NUMS];
int n,e;
}Graph;
void Dispath(int A[][NUMS],int path[][NUMS],int n);
void ReadGraph(Graph *G){ //从文件中读取,每次手打实在是麻烦
int i,j;
FILE * fp = fopen("floyd.txt","rw");
G->n = NUMS;
G->e = NUMS * NUMS;
for(i=0; i<NUMS; i++){
for(j=0; j<NUMS; j++){
fscanf(fp,"%d",&(G->edges[i][j]));
printf("%d \t",G->edges[i][j]);
}
printf("\n");
}
}
void Floyd(Graph G){
int A[NUMS][NUMS],path[NUMS][NUMS];
int i,j,k;
for (i=0;i<G.n;i++){
for (j=0;j<G.n;j++){
A[i][j]=G.edges[i][j];
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 (A[i][j]>A[i][k]+A[k][j]){
A[i][j]=A[i][k]+A[k][j];
path[i][j]=k;
}
}
}
}
Dispath(A,path,G.n);
}
void Spath(int path[][NUMS],int i,int j){
int k;
k=path[i][j];
if (k==-1){
return;
}
Spath(path,i,k);
printf("%d,",k + 1);
Spath(path,k,j);
}
void Dispath(int A[][NUMS],int path[][NUMS],int n){
int i,j;
for (i=0;i<n;i++){
for (j=0;j<n;j++){
if (A[i][j]==999999999){
if (i!=j){
printf("从%d到%d没有路径\n",i+1,j+1);
}
}
else{
printf(" 从%d到%d => 最短路径长度为: %d , 路径经过:",i+1,j+1,A[i][j]);
printf("%d,",i + 1);
Spath(path,i,j);
printf("%d\n",j + 1);
}
}
}
}
int main(){
Graph G;
ReadGraph(&G);
Floyd(G);
return 0;
}
算法分析
Dijkstra:O(n^2)
Floyd:O(n^3)