dijkstra 模板

/*************************************************************************
     File Name: str.cpp
     Author: yubo
     Mail: yuzibode@126.com 
     Created Time: 2014年05月02日 星期五 04时55分27秒
     学习重点:
	 1.dijsktra:用到了图结构,有向图edges[i][j]表示从定点i到定点j的权值
	  在输入的时候edges[i][j]=edges[j][i]=c,就可以计算无向图的
	 2.原点可以随意指定,dis数组保存的是从原点到各点的最小距离
	 3.sum up:先定于一点v, 然后一个for循环,将与定点v直接联系的定点的距离
	 赋给dis,借此机会把s集合清0,从v开始,同时置s【v】=1,表示v进入集合s依次
	 进行。既然把从原点到各点的最短距离求出来了,害怕到固定点吗?直接定位dist[i]输出就可以了啊。两者的时间复杂度都是n^2.
	   保存路径的问题也已经解决,算法中数组prev[i]记录的是从源点到顶点i的最短路径上i的前一个顶点。初始化时,对所有与源点有直接关联的点置prev[i]=v,然后在更新长度是令prev【i】=u。保存后怎么利用呢,比如我想知道从源点1到3的路径,是这样的:
	   k=1;short【k】=3;从这个点往前推,prev[short[k]]==0为止,最后倒序输出就行了。
	   那么单个点同样直接定位。
	 4.现在实现了把路径给弄出来了,只能说代码太帅了
	 5.限用条件:权值只能是非负的;每条路径只能有一条边
	 .作为模板,需要自己改动
 ************************************************************************/
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
int edges[100][100];
int dis[100];//存储路径长度
int s[100];//集合s,数组随题意改变啊
int prev[100];//保存结点的前点
#define MAXN 100000000
int n,m;
void dijkstra(int v)
{
	printf("hjfgu\n");
	for(int i=1;i<=n;i++)
	{
		dis[i]=edges[v][i];
		s[i]=0;
		if(dis[i]==MAXN) 
			prev[i]=0;//注意在设置数组的时候,如果顶点是从0开始的,这里jiu要
					//做修改
		else
			prev[i]=v;//这说明是直接相关联的
	}
	dis[v]=0;s[v]=1;//原点已经加入到集合中
	for(int i=1;i<n;i++)//Be carefully
	{
		int temp=MAXN;
		int u=v;
		for(int j=1;j<=n;j++)//千万
		{
			if((!s[j])&&(dis[j]<temp))
			{
				u=j;temp=dis[j];
			}
		}
		s[u]=1;
		for(int j=1;j<=n;j++)
		{
			if((!s[j])&&(edges[u][j]<MAXN)){
				if(dis[j]>dis[u]+edges[u][j])//确定一点u后,并不算完,还要
					                        //根据u更新edges【u】【j】和dis
											//[u],这也是重点
					dis[j]=dis[u]+edges[u][j];
				prev[j]=u;
			}
		}

	}
	printf("%d\n",dis[1]);
}
int main()
{
	freopen("in.txt","r",stdin);
	int a,b,c;
	int shortest[100]; 
	while(cin>>n>>m){//输入结点数和边数
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				edges[i][j]=MAXN;
			}
		}
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			edges[b][a]=edges[a][b]=c;//修改这里可以变为有向图
		}
		int i;
		dijkstra(1);
           // 在这里运用了倒向追踪的方法,That's what?  
            for( i=2;i<=n;i++)  
            {  
                printf("%d\t",dis[i]);//输出各顶点时存放的序号  
                memset(shortest,0,sizeof(shortest));  
                int k=1;//  
                shortest[k]=i;  
                while(prev[shortest[k]]!=0)  
                {  
                    k++;  
                    shortest[k]=prev[shortest[k-1]];  
                }  
               // k++;  
                shortest[k]=1;  
                for(int j=k;j>1;j--)  
                    printf("%d-->",shortest[j]);  
                printf("%d\n",shortest[1]);  
            }  
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值