最小花费最短路
(第一次从外网登陆,像个傻子一样输了半天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; }