http://acm.hdu.edu.cn/showproblem.php?pid=3790&&最短路径问题

127 篇文章 0 订阅
67 篇文章 0 订阅
Problem Description
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。


Input
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)


Output
输出 一行有两个数, 最短距离及其花费。


Sample Input
3 2
1 2 5 6
2 3 4 5
1 3
0 0


Sample Output
9 11

AC代码:

#include<iostream>
#include<string.h>
#include<algorithm>
#include<limits.h>
#define M 99999999
#define N 1005
#define  FOR(i,s,t) for(int i=(s);i<=t;++i)
using namespace std;
int dist[N];
int pas[N];
int map[N][N];
int pay[N][N];
bool visit[N];
int n,m,p,q;
void  Dijstra()
{  int now=p;
    dist[now]=0;
    pas[now]=0;
    visit[now]=false;
    FOR(i,1,n)
    {  FOR(j,1,n)
        if(visit[j])
         {
         if(dist[j]>dist[now]+map[now][j])
          {dist[j]=dist[now]+map[now][j];
            pas[j]=pas[now]+pay[now][j];
           }
           else if(dist[j]==dist[now]+map[now][j]&&pas[j]>pas[now]+pay[now][j])
               pas[j]=pas[now]+pay[now][j]; 
           }
          int minx=M;
          FOR(j,1,n)
          if(visit[j]&&dist[j]<minx)
           minx=dist[now=j];
           visit[now]=false;
     }
     cout<<dist[q]<<" "<<pas[q]<<endl;
      }
int main()
{   while(cin>>n>>m&&n&&m)
    {   FOR(i,1,n)
         FOR(j,1,n)
         { dist[i]=M;
            map[i][j]=M;
             visit[i]=true;
             pas[i]=M;
             pay[i][j]=M;
            }
            FOR(i,1,m)
             { int a,b,c,d;
                cin>>a>>b>>c>>d;
                if(map[a][b]>c)
                 {map[a][b]=map[b][a]=c;
                   pay[a][b]=pay[b][a]=d;
                 }
                 }
                  cin>>p>>q;
                 Dijstra();
                 
                 } return 0;
    
    }


spfa+优先队列优化:

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<queue>
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define N 200005
#define M 1005
#define MAX 999999999
using namespace std;
typedef struct node
{
	int num;
	int len;
	int cost;
	int Next;
	friend bool operator<(node a,node b)
	{return a.len>b.len;}
}Node;
Node s[N];
int n,m,dis[M],pay[M],head[M],res;
bool vis[M];
void init()
{
	res=0;
	CLR(head,-1);
	for(int i=1;i<=n;++i) pay[i]=MAX,dis[i]=MAX;
	CLR(vis,false);
}
void add(int a,int b,int c,int d)
{
	s[res].num=b;
	s[res].len=c;
	s[res].cost=d;
	s[res].Next=head[a];
	head[a]=res++;
}
void SPFA(int sta)
{
	priority_queue<int>Q;
	Q.push(sta);
	vis[sta]=true;
	pay[sta]=0;
	dis[sta]=0;
	while(!Q.empty())
	{
		int v=Q.top();
		  Q.pop();
		  vis[v]=false;
		  for(int i=head[v];i!=-1;i=s[i].Next)
		  {
			  int len=s[i].len;
			  int cost=s[i].cost;
			  int u=s[i].num;
			  if(dis[u]>dis[v]+len)
			  {
				  dis[u]=dis[v]+len;
				  pay[u]=pay[v]+cost;
				  if(!vis[u])
				  {
					  Q.push(u);
					  vis[u]=true;
				  }
			  }
			  else if(dis[u]==dis[v]+len&&pay[u]>pay[v]+cost)
			  {
				   pay[u]=pay[v]+cost;
				  if(!vis[u])
				  {
					  Q.push(u);
					  vis[u]=true;
				  }
			  }
		  }
	}
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		init();
		if(!n&&!m) break;
		for(int i=0;i!=m;++i)
		{
			int a,b,c,e;
			scanf("%d%d%d%d",&a,&b,&c,&e);
			add(a,b,c,e);
			add(b,a,c,e);
		}
		int sta,end;
		scanf("%d%d",&sta,&end);
		SPFA(sta);
		printf("%d %d\n",dis[end],pay[end]);
	}return 0;
}


dijstra+优先队列优化:

#include<iostream>
#include<string.h>
#include<cstdio>
#include<string>
#include<limits.h>
#include<queue>
#define N 200005
#define M 999999999
using namespace std;
typedef struct node
{
    int num;
    int len;
    int Next;
    int cost;
}Node;
int res,head[1005],dis[1005],n,pay[1005];
Node s[N];
typedef pair<int,int> pii;
void init()
{
    memset(head,-1,sizeof(head));
    res=0;
}
void add(int a,int b,int c,int d)
{
    s[res].num=b;
    s[res].len=c;
    s[res].cost=d;
    s[res].Next=head[a];
    head[a]=res++;
}
void dijstra(int sta)
{
    bool vis[1005];
    for(int i=1;i<=n;++i) dis[i]=(i==sta)?0:M,pay[i]=(i==sta)?0:M,vis[i]=false;
    priority_queue<pii,vector<pii>,greater<pii> >Q;
    Q.push(make_pair(dis[sta],sta));
    while(!Q.empty())
    {
        pii u=Q.top();
        Q.pop();
        int x=u.second;
        if(vis[x]) continue;
        vis[x]=true;
        for(int i=head[x];i!=-1;i=s[i].Next)
            if(dis[s[i].num]>dis[x]+s[i].len)
             {
                dis[s[i].num]=dis[x]+s[i].len;
                pay[s[i].num]=pay[x]+s[i].cost;
                Q.push(make_pair(dis[s[i].num],s[i].num));
             }
            else if(dis[s[i].num]==dis[x]+s[i].len)
            {
                if(pay[s[i].num]>pay[x]+s[i].cost)
                   {
                       pay[s[i].num]=pay[x]+s[i].cost;
                      Q.push(make_pair(dis[s[i].num],s[i].num));
                   }
            }
    }
}
int main()
{
    int m;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        if(!n&&!m) break;
        for(int i=0;i!=m;++i)
        {
            int a,b,c,e;
            scanf("%d%d%d%d",&a,&b,&c,&e);
            add(a,b,c,e);
            add(b,a,c,e);
        }
        int sta,end;
        scanf("%d%d",&sta,&end);
        dijstra(sta);
        printf("%d %d\n",dis[end],pay[end]);
    }return 0;
}


spfa+优先队列优化的:125ms

dijs+优先队列优化的:109ms
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值