关闭

图的综合实验(Dijkstra算法)

标签: 算法dijkstra
1048人阅读 评论(0) 收藏 举报
分类:

Problem:

     给定n个村庄之间的交通图。若村庄ij之间有路可通,则ij用边连接,边上的权值Wij表示这条道路的长度。现打算在这n个村庄中选定一个村庄建一所医院。编写如下算法:(村庄为无向图,但所写算法对于其加强命题有向图也须成立)

(1) 求出该医院应建在哪个村庄,才能使距离医院最远的村庄到医院的路程最短。

(2) 求出该医院应建在哪个村庄,能使其它所有村庄到医院的路径总和最短。

Tips:

     对于(1),可以先求出每个村庄到其它所有村庄的最短路径,保存其最大值(表示假设医院建在该村庄,距离医院最远的村庄的路径长度);然后在这些最大值中找出一个最小值。

    对于(2),可以先求出每个村庄到其它所有村庄的最短路径,保存其累加和(表示假设医院建在该村庄,其它所有村庄距离医院的路径总和);然后在这些和中找出一个最小值。

#include<stdio.h>
#define	INF	1000000
#define UINF -1000000
#define MAXV 100
//创建最短路径返回值的结构体
typedef struct
{
	int dist[MAXV],path[MAXV];
	int s[MAXV],n,v;
}DijValue;
//创建图
typedef struct
{	int edges[MAXV][MAXV];
	int n;
}MGraph;

void CreateGraph(MGraph &g)
{	int i,j;
	printf("输入村庄个数:");
	scanf("%d",&g.n);  
	printf("输入路径权值(若不直接相连输入-1)\n");
	for(i=0;i<g.n;i++) 
	{	printf("\t依次输入顶点%d到顶点0~%d的权值:",i,g.n-1);
		for(j=0;j<g.n;j++)
		{
			scanf("%d",&g.edges[i][j]);
			if(g.edges[i][j]==-1)
				g.edges[i][j]=INF;
		}
		printf("\n");
	}
}
//输出路径
void Ppath(int path[],int k,int v)
{   int i;
	i=path[k];
	if(i==v){printf("%d=>%d",i,k);return;}
	Ppath(path,i,v);
	printf("=>%d",k);
}

//最短路径算法
void Dijkstra (MGraph g,int v,DijValue *Temp)
{	int dist[MAXV],path[MAXV];
	int s[MAXV];
	int mindis,i,j,u;
	for(i=0;i<g.n;i++)
	{	dist[i]=g.edges[v][i];
		s[i]=0;
		if(g.edges[v][i]<INF)
			path[i]=v;    		
		else
			path[i]=-1;			//i与v没边时置i前一个顶点为-1
	}
	s[v]=1;path[v]=v;			
	for(i=0;i<g.n;i++)
	{	mindis=INF;
		for(j=0;j<g.n;j++)		//寻找新最短dist[]到S中
			if(s[j]==0&&dist[j]<mindis)
			{	u=j;
				mindis=dist[j];
			}
			s[u]=1;
			for(j=0;j<g.n;j++)	//新一轮的dist[]
				if(s[j]==0)
					if(g.edges[u][j]<INF&&dist[u]+g.edges[u][j]<dist[j])
					{	dist[j]=dist[u]+g.edges[u][j];
						path[j]=u;
					}
	}
	Temp->n=g.n;
	Temp->v=v;
	for(int k=0;k<g.n;k++)
	{
		Temp->dist[k]=dist[k];
		Temp->path[k]=path[k];
		Temp->s[k]=s[k];
	}
}
//问题一:距离医院最远的村庄到医院的路程最短
void Question_One(MGraph g)
{
	int i,j,flag=1,item;
	int max=UINF;
	int min=INF;
	int Number,Number2;
	DijValue Temp1;
	printf("Question1:\n");
	for(i=0;i<g.n;i++)
	{
		Dijkstra(g,i,&Temp1);
		for(j=0;j<g.n;j++)							//求每个医院最远村庄
		{
			if(Temp1.s[j]==1&&Temp1.dist[j]>max)
			{	max=Temp1.dist[j];
				item=j;
			}
		}
		if(flag){printf("\t从每个村庄出发的最短路径的最长值:\n\t");flag=0;}
		printf("long[%d]=%d  ",i,max);
		if(max<min)									//最远村庄中的最近的
		{
			min=max;
			Number=i;
			Number2=item;
		}
		max=UINF;
	}
	printf("\n\t所以距离医院最远的村庄的最近路程为:\n\tlong[%d]=%d\n",Number,min);
	Dijkstra(g,Number,&Temp1);
	printf("\t具体路线为:");
	Ppath(Temp1.path,Number2,Number);				//输出路径
	printf("\n");
}
//问题二:所有村庄到医院的路径总和最短
void Question_Two(MGraph g)
{
	int i,j,sum=0,flag=1;
	int min=INF;
	int Number;
	DijValue Temp2;
	printf("Question2:\n");
	for(i=0;i<g.n;i++)
	{
		Dijkstra(g,i,&Temp2);
		for(j=0;j<g.n;j++)							//路程和
		{
			if(Temp2.s[j]==1)
				sum+=Temp2.dist[j];
		}
		if(flag){printf("\t从各自每个村庄出发的路程总和:\n\t");flag=0;}
		printf("sum[%d]=%d  ",i,sum);
		if(sum<min)									//最小路程和
		{
			min=sum;
			Number=i;
		}
		sum=0;
	}
	printf("\n\t所以到其它所有村庄路径总和最短的村庄:\n\tsum[%d]=%d\n",Number,min);
}
int main(void)
{   int sovle,flag=1;
	MGraph graphMin;
	while(flag)
	{   
		printf("\t\t\t\t求解--1,退出--0:");
		scanf("%d",&sovle);
		switch(sovle)
		{   case 0:flag=0;break; 
			case 1:
				{	CreateGraph(graphMin);
				    Question_One(graphMin);
				    Question_Two(graphMin);
					break;
				}
		}
	}
	return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1955次
    • 积分:73
    • 等级:
    • 排名:千里之外
    • 原创:5篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类