最小花费最短路

(第一次从外网登陆,像个傻子一样输了半天QQ账号和密码,还纳闷怎么进不去)

【题目描述】:

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

【输入描述】:

多组数据:每组数据描述如下:

输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。

n和m为0时输入结束。

【输出描述】:

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

【样例输入】: 3 2 1 2 5 6 2 3 4 5 1 3 0 0

【样例输出】: 9 11

【时间限制、数据范围及描述】:

时间:1s 空间:128M

对于 30%的数据:1<n<=100

对于100%的数据:1<n<=1000; 0<m<100000; s != t; 1<=d,p<=1000

数据组数<=5,注意卡常;

Dijsktra算法,据说SPFA也过了。

邻接矩阵耗时1000ms,加上快读优化300ms(然而光矩阵其实就能过······)(如果再加上手动O2,会再快0~40ms)

min自己写一下速度好想要快一点(长知识了)

据说正解是堆加优化,但事实证明,某位按正解做的人时间还没我快······

#include<cstdio>
#include<iostream> 
#include<cstring>
#include<algorithm>
using namespace std;

#define INF 0x3f3f3f3f

#define min(a,b) a>b?b:a

struct Node
{
    int adj,val;
}g[1005][1005];

int dist[1005];

int value[1005]; 

int used[1005];//标记是否走过

int n,m,i,j;

inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}//纯属好玩

void Dijkstra(int s){
    memset(dist,0x3f,sizeof(dist));
    memset(value,0x3f,sizeof(value));
    memset(used,0,sizeof(used));
    dist[s]=0;
    value[s]=0;
    while(1){
        int k,u=-1,d[1005]; 
        int min=INF;
        memset(d,0,sizeof(d));
        for(i=1;i<=n;i++){
            if(used[i]==0&&dist[i]<min)
            {
                min=dist[i];
                u=i;
            }
        }
        if(u==-1){
            return ;
        }
        for(i=1,k=0;i<=n;i++){
            if(dist[u]==dist[i]&&used[i]==0){
                d[k++]=i;
            }
        }
        for(i=0;i<k;i++){
            used[d[i]]=1;
        }
        for(i=0;i<k;i++){
            for(j=1;j<=n;j++){
                if(g[d[i]][j].adj!=INF && (dist[d[i]]+g[d[i]][j].adj)<=dist[j])
                {
                    if((dist[d[i]]+g[d[i]][j].adj)<dist[j])
                        value[j]=value[d[i]]+g[d[i]][j].val;
                    else
                        value[j]=min(value[j],value[d[i]]+g[d[i]][j].val);
                    dist[j]=dist[d[i]]+g[d[i]][j].adj;
                }
            }
        }
    }
}

int main(){
    while((n=read(),m=read()) && (n!=0&&m!=0)){
        int a,b,d,p;
        memset(g,0x3f,sizeof(g));
        for(i=1;i<=m;i++){
            a=read();
            b=read();
            d=read();
            p=read();
            if(d<=g[a][b].adj){
                if(d==g[a][b].adj){
                    g[a][b].val=g[b][a].val=min(p,g[a][b].val);
                }
                else{
                    g[a][b].val=g[b][a].val=p;
                }
                g[a][b].adj=g[b][a].adj=d; 
            }
        }
        int s,t;
        s=read();
        t=read();
        Dijkstra(s);
        printf("%d %d\n",dist[t],value[t]);
    }
    return 0;
}

 

posted @ 2019-07-05 17:16  魂兮龙游  阅读(338)  评论(0编辑  收藏  举报