算法导论 所有结点最短路径问题 Johnson

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "FIB.h"

//图节点  
typedef struct VertexNode  
{  
    char name;  
    VertexNode *p; 
	int key;
	pFNode pf;
	int tempKey;
}Vertex,*pVertex;  
  
//图  
typedef struct   
{  
    int vn;  
    int **E;  
    pVertex *V;  
    int **tempE;  
}Graph,*pGraph;  
//根据算法导论 图25-6初始化图,Johnson的加入0结点和构造冗余边放在初始化中,这里不动态产生,因为懒 
pGraph initGraph()  
{  
    pGraph g=(pGraph)malloc(sizeof(Graph));  
    g->vn=6;  
	pVertex v0=(pVertex)malloc(sizeof(Vertex));  
    v0->name='0';
    v0->p=NULL; 
    pVertex v1=(pVertex)malloc(sizeof(Vertex));  
    v1->name='1';    
    v1->p=NULL;  
    pVertex v2=(pVertex)malloc(sizeof(Vertex));  
    v2->name='2';    
    v2->p=NULL;  
    pVertex v3=(pVertex)malloc(sizeof(Vertex));  
    v3->name='3';   
    v3->p=NULL;  
    pVertex v4=(pVertex)malloc(sizeof(Vertex));  
    v4->name='4';    
    v4->p=NULL;  
    pVertex v5=(pVertex)malloc(sizeof(Vertex));  
    v5->name='5';   
    v5->p=NULL;  
  
    g->V=(pVertex*)malloc(g->vn*sizeof(pVertex));  
    g->V[0]=v0;  
    g->V[1]=v1;  
    g->V[2]=v2;  
    g->V[3]=v3;  
    g->V[4]=v4; 
	g->V[5]=v5;
  
    g->E = (int**)malloc(g->vn*sizeof(int*));  
	g->tempE= (int**)malloc(g->vn*sizeof(int*));  
    for(int i=0;i<g->vn;i++)  
    {  
        g->E[i]=(int*)malloc(g->vn*sizeof(int));  
		 g->tempE[i]=(int*)malloc(g->vn*sizeof(int));  
    }  
    for(int i=0;i<g->vn;i++)  
    {  
        for(int j=0;j<g->vn;j++)  
        { 
			if(i==j)
				g->E[i][j]=0;
			else
				g->E[i][j]=INT_MAX;  
        }  
    }  
	g->E[0][1]=0;
	g->E[0][2]=0;
	g->E[0][3]=0;
	g->E[0][4]=0;
	g->E[0][5]=0;
    g->E[1][2]=3;  
    g->E[1][3]=8;  
	g->E[1][5]=-4;
    g->E[2][4]=1;  
    g->E[2][5]=7;  
    g->E[3][2]=4;  
    g->E[4][3]=-5;
	g->E[4][1]=2;
    g->E[5][4]=6;  
    return g;  
}  

void relax(pGraph g,int u,int v)
{
	//无边,不进行松弛
	if(g->E[u][v]==INT_MAX)
		return;
	int sum,uk=g->V[u]->key,vk=g->V[v]->key,ew=g->E[u][v];
	//根据规则,加上无穷等于无穷
	if(uk==INT_MAX || ew==INT_MAX)
		sum=INT_MAX;
	else
		sum=uk+ew;
	if(vk>sum)
	{
		g->V[v]->key=sum;
		g->V[v]->p=g->V[u];
	}
}


void relaxFIB(pGraph g,int u,int v,pFIB h)
{
	//无边,不进行松弛
	if(g->tempE[u][v]==INT_MAX)
		return;
	int sum,uk=g->V[u]->tempKey,vk=g->V[v]->tempKey,ew=g->tempE[u][v];
	//根据规则,加上无穷等于无穷
	if(uk==INT_MAX || ew==INT_MAX)
		sum=INT_MAX;
	else
		sum=uk+ew;
	if(vk>sum)
	{
		g->V[v]->tempKey=sum;
		g->V[v]->p=g->V[u];
		FIB_heap_decreaseKey(h,g->V[v]->pf,sum);
	}
}

bool BellmanFord(pGraph g)
{
	for(int i=1;i<=g->vn-1;i++)
	{
		for(int j=0;j<g->vn;j++)
		{
			for(int k=0;k<g->vn;k++)
			{
				if(g->E[j][k]<INT_MAX)
					relax(g,j,k);
			}
		}
	}
	for(int u=0;u<g->vn;u++)
	{
		for(int v=0;v<g->vn;v++)
		{
			if(g->E[u][v]>0)
			{
				int sum,uk=g->V[u]->key,vk=g->V[v]->key,ew=g->E[u][v];
				//根据规则,加上无穷等于无穷
				if(uk==INT_MAX || ew==INT_MAX)
					sum=INT_MAX;
				else
					sum=uk+ew;
				if(vk>sum)
					return false;
			}
		}
	}
	return true;
}

void Dijikstra(pGraph g)
{
	pFIB h=make_FIB_heap();
	for(int i=1;i<g->vn;i++)
	{
		pFNode pf=createNode(g->V[i]->tempKey);
		g->V[i]->pf=pf;
		pf->vi=i;
		FIB_heap_insert(h,pf);
	}
	while(h->n>0)
	{
		pFNode uf=FIB_heap_extract_min(h);
		int u=uf->vi;
		for(int v=0;v<g->vn;v++)
		{
			if(g->tempE[u][v]<INT_MAX)
				relaxFIB(g,u,v,h);
		}
	}
}

void printKey(pGraph g)
{
	for(int i=0;i<g->vn;i++)
		printf("%d ",g->V[i]->key);
	printf("\n");
}

void printD(int **D,int n)
{
	for(int i=1;i<n;i++)
	{
		for(int j=1;j<n;j++)
		{
			if(D[i][j]<INT_MAX && D[i][j]>INT_MIN)
				printf("%2d ",D[i][j]);
			else
				printf("%2c ",'*');
		}
		printf("\n");
	}
}

int **Johnson(pGraph g)
{
	int **D= (int**)malloc(g->vn*sizeof(int*));  
	int **L= (int**)malloc(g->vn*sizeof(int*));
    for(int i=0;i<g->vn;i++)  
    {  
        D[i]=(int*)malloc(g->vn*sizeof(int)); 
		L[i]=(int*)malloc(g->vn*sizeof(int));
    }  

	for(int i=0;i<g->vn;i++)
	{
		if(i==0)
			g->V[i]->key=0;
		else
			g->V[i]->key=INT_MAX;
	}
	bool b=BellmanFord(g);
	//printKey(g);
	if(!b)
	{
		printf("the input graph contains a negative-weight cycle");
		return NULL;
	}
	else
	{
		for(int u=0;u<g->vn;u++)
		{
			for(int v=0;v<g->vn;v++)
			{
				if(g->E[u][v]<INT_MAX)
					g->tempE[u][v]=g->E[u][v]+g->V[u]->key-g->V[v]->key;
				else
					g->tempE[u][v]=INT_MAX;
			}
		}
		//printD(g->tempE,g->vn);
		for(int u=1;u<g->vn;u++)
		{
			for(int i=1;i<g->vn;i++)
			{
				g->V[i]->pf=NULL;
				if(i==u)
					g->V[i]->tempKey=0;
				else
					g->V[i]->tempKey=INT_MAX;
			}
			Dijikstra(g);
			for(int j=1;j<g->vn;j++)
			{
				int t=g->V[j]->tempKey;
				L[u][j]=g->V[j]->tempKey;
			}
		}
		//printD(L,g->vn);
		for(int u=1;u<g->vn;u++)
		{
			for(int v=1;v<g->vn;v++)
			{
				D[u][v]=L[u][v]+g->V[v]->key-g->V[u]->key;
			}
		}
	}
	return D;
}



void main()
{
	pGraph g=initGraph();
	int **D=Johnson(g);
	printD(D,g->vn);
	getchar();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值