zoukankan      html  css  js  c++  java
  • HDOJ 2544 最短路(最短路径 dijkstra算法,SPFA邻接表实现,floyd算法)

    最短路

    Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 42716    Accepted Submission(s): 18715


    Problem Description
    在每年的校赛里,全部进入决赛的同学都会获得一件非常美丽的t-shirt。可是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!

    所以如今他们想要寻找最短的从商店到赛场的路线。你能够帮助他们吗?

     

    Input
    输入包含多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。

    接下来M行。每行包含3个整数A。B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路。我们的工作人员须要C分钟的时间走过这条路。
    输入保证至少存在1条商店到赛场的路线。

     

    Output
    对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
     

    Sample Input
    2 1 1 2 3 3 3 1 2 5 2 3 5 3 1 2 0 0
     

    Sample Output
    3 2
     
     
    第一道最短路径。感觉dijkstra和prim非常像嘛。

     
    dijkstra算法,代码例如以下:
     
    #include<cstdio>
    #include<cstring>
    #define max 110
    #define INF 0x3f3f3f
    int n,map[max][max];//map记录两点间的最短路径 
    
    void dijkstra()
    {
        int dis[max];//记录起始点到当前点的最短路径 
    	int visit[max];//标记是否訪问过了 
        int i,j,next,min;
        memset(visit,0,sizeof(visit));
        for(i=1;i<=n;i++)
           dis[i]=map[1][i];
        visit[1]=1;
        for(i=2;i<=n;++i)
        {
            min=INF;
            for(j=1;j<=n;++j)
            {
                if(visit[j]==0&&min>dis[j])
                {
                    min=dis[j];
                    next=j;
                }
            }
            visit[next]=1;
            for(j=1;j<=n;j++)
            {
                if(visit[j]==0&&dis[j]>dis[next]+map[next][j])
                    dis[j]=dis[next]+map[next][j];
            }
        }
        printf("%d
    ",dis[n]);
    }
    
    int main()
    {
        int m,a,b,c;
        while(scanf("%d%d",&n,&m)&&n||m)
        {
            memset(map,INF,sizeof(map));
            while(m--)
            {
                scanf("%d%d%d",&a,&b,&c);
                if(map[a][b]>c)
                    map[a][b]=map[b][a]=c;
                
            }
            dijkstra();
        }
        return 0;
    }
     
     
     
     
     
    补充下SPFA算法,SPFA求解最短路要建立邻接表,实现过程中用队列储存当前遍历到的点。能够理解为无权图的BFS转化为了有权图。
     
    代码例如以下:
     
    <span style="font-size:12px;">#include<cstdio>
    #include<cstring>
    #include<queue>
    #define INF 0x3f3f3f
    #define maxn 110//点数 
    #define maxm 10010//边数 
    using namespace std;
    int dis[maxn];//储存起点到当前点的最短路 
    int visit[maxn];//标记当前点是否在队列中 
    int head[maxn];
    int n,top;
    
    struct node
    {
    	int to,val,next;
    }edge[maxm];
    
    void add(int a,int b,int c)//建立邻接表 
    {
    	edge[top].to=b;
    	edge[top].val=c;
    	edge[top].next=head[a];//指向上一个。edge[].next指向的是前一个,相当于链表里的指针的作用   
    	head[a]=top++;
    }
    
    void spfa(int start)
    {
    	int i,j,next,u,v;
    	queue<int>q;
    	for(i=1;i<=n;++i)
    	   dis[i]=INF;
    	dis[start]=0;
    	visit[start]=1;
    	q.push(start);
    	while(!q.empty())
    	{
    		u=q.front();
    		q.pop();
    		visit[u]=0;//消除标记 
    		for(i=head[u];i!=-1;i=edge[i].next)//遍历以u为前点的全部边 
    		{
    			v=edge[i].to;
    			if(dis[v]>dis[u]+edge[i].val)
    			{
    				dis[v]=dis[u]+edge[i].val;
    				if(!visit[v])
    				{
    					visit[v]=1;
    					q.push(v);
    				}
    			}
    		}
    	}
    	printf("%d
    ",dis[n]);
    }
    
    int main()
    {
    	int m,i,a,b,c;
    	while(scanf("%d%d",&n,&m)&&n||m)
    	{
    		top=0;//建表从零開始 
    		for(i=1;i<=n;++i)
    		{
    			visit[i]=0;
    			head[i]=-1;
    		}
    		while(m--)
    		{
    			scanf("%d%d%d",&a,&b,&c);
    			add(a,b,c);
    			add(b,a,c);
    		}
    		spfa(1);
    	}
    	return 0;
    }</span>

     
     

    floyd算法还是比較easy理解的,代码也简单介绍,可是时间复杂度太大。

    代码例如以下:

    <span style="font-size:14px;">#include<cstdio>
    #define maxn 110
    #define INF 0x3f3f3f
    int dis[maxn][maxn],n;
    
    void floyd()
    {
    	int k,i,j;
    	for(k=1;k<=n;++k)
    	{
    		for(i=1;i<=n;++i)
    		{
    			for(j=1;j<=n;++j)
    			{
    				if(dis[i][j]>dis[i][k]+dis[k][j])
    				    dis[i][j]=dis[i][k]+dis[k][j];
    			}
    		}
    	}
    	printf("%d
    ",dis[1][n]);
    }
    
    int main()
    {
    	int m,i,j,a,b,c;
    	while(scanf("%d%d",&n,&m)&&n||m)
    	{
    		for(i=1;i<=n;++i)
    		{
    			for(j=1;j<=n;++j)
    			{
    				if(i==j)
    				   dis[i][j]=0;
    				else
    				   dis[i][j]=INF;
    			}
    		}
    		while(m--)
    		{
    			scanf("%d%d%d",&a,&b,&c);
    			if(dis[a][b]>c)
    			    dis[a][b]=dis[b][a]=c;
    		}
    		floyd();
    	}
    	return 0;
    }</span>


     

  • 相关阅读:
    关于ADMM的研究(一)
    BAT染指影视制作 欲全面撬开互联网粉丝经济
    把安卓源代码中的system app独立出来,像开发普通app那样开发
    Java数学表示式解析工具- jeval
    android monkey
    tomcat URL简写案例:模拟站点www.baidu.com的訪问
    Ajax 跨域请求 jsonp获取json数据
    Android 开源项目android-open-project解析之(三) ScrollView,TimeView,TipView,FlipView
    iOS-获取UIView的全部层级结构
    定制属于自己的Chrome起始页
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7040050.html
Copyright © 2011-2022 走看看