#216. 最小花费最短路
【题目描述】:
给你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,注意卡常;
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
int n,m,s,t,Cnt,Next[5000001],head[5000001],to[5000001];
bool visit[5000001];
int dis[5000001],Cost[5000001],val[5000001],cost[5000001];
struct cmp{
bool operator()(int a,int b){
return dis[a]>dis[b];
}
};
void Push(int x,int y,int z,int c){
++Cnt;
Next[Cnt]=head[x];
head[x]=Cnt;
to[Cnt]=y;
val[Cnt]=z;
cost[Cnt]=c;
}
void dijkstra(){
priority_queue<int,vector<int>,cmp> Q;
for(int i=1;i<=n;i++){
visit[i]=false;
dis[i]=1000000001;
Cost[i]=1000000001;
}
Q.push(s);
visit[s]=true;
dis[s]=0;
Cost[s]=0;
while(!Q.empty()){
int u=Q.top();
Q.pop();
visit[u]=false;
for(int i=head[u];i;i=Next[i]){
int v=to[i];
if(dis[v]>dis[u]+val[i]||(Cost[v]>Cost[u]+cost[i]&&dis[v]==dis[u]+val[i])){
Cost[v]=Cost[u]+cost[i];
dis[v]=dis[u]+val[i];
if(!visit[v]){
visit[v]=true;
Q.push(v);
}
}
}
}
return;
}
int main(){
int u,v,w,c;
while(scanf("%d%d",&n,&m)){
memset(head,0,sizeof(head));
if(n==0||m==0){
break;
}
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&u,&v,&w,&c);
Push(u,v,w,c);
Push(v,u,w,c);
}
scanf("%d%d",&s,&t);
dijkstra();
printf("%d %d\n",dis[t],Cost[t]);
}
return 0;
}
此题很烦。
花了好长时间。