给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
(1<n<=1000, 0<m<100000, s != t)
3 2 1 2 5 6 2 3 4 5 1 3 0 0
output
9 11
这道题坑死了,用普通的迪杰斯特拉算法一下子就AC了,后来用优先队列写,用G++提交错了N次,后来终于发现是优先队列返回的函数写错了。(不知道为什么函数写错了,用C++提交竟然能AC,可能C++会默认返回值吧。我也不是很懂。)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int INF=1<<30;
struct Node {
int k;
int dist;
int cost;
};
bool operator <(const Node &a,const Node &b) {
if(a.dist!=b.dist)
return a.dist>b.dist;
else if(b.dist==a.dist)
return b.cost<a.cost;
}
Node map1[1005][1005];
int vist[1005];
int s,en,mind,minc;
priority_queue<Node>que;
void init(int n) {
for(int i=0; i<=n+1; i++) {
vist[i]=0;
for(int j=0; j<=n+1; j++) {
map1[i][j].dist=map1[i][j].cost=INF;
}
}
}
int main() {
int n,m;
while(~scanf("%d%d",&n,&m)) {
if(n==0&&m==0) break;
init(n);
while(m--) {
int x,y,d,p;
scanf("%d%d%d%d",&x,&y,&d,&p);
if(map1[x][y].dist==d) {
if(map1[x][y].cost>p)
map1[x][y].cost=map1[y][x].cost=p;
} else if(map1[x][y].dist>d) {
map1[x][y].dist=map1[y][x].dist=d;
map1[x][y].cost=map1[y][x].cost=p;
}
}
scanf("%d%d",&s,&en);
Node q;
q.dist=0,q.cost=0,q.k=s;
que.push(q);
mind=INF;
minc=INF;
while(!que.empty()) {
q=que.top();
que.pop();
if(q.k==en ) {
if(mind>q.dist) {
mind=q.dist;
minc=q.cost;
} else if(mind==q.dist) {
minc=min(q.cost,minc);
}
}
if(vist[q.k]) continue;
vist[q.k]=1;
for(int i=1; i<=n; i++) {
if(map1[q.k][i].dist<INF && !vist[i]) {
Node p;
p.dist=map1[q.k][i].dist+q.dist;
p.cost=map1[q.k][i].cost+q.cost;
p.k=i;
que.push(p);
}
}
}
printf("%d %d\n",mind,minc);
}
return 0;
}
下面是错误的一段代码,你们可以试一试用C++和G++提交,就会发现前者AC,后者wa。。
bool operator <(const Node &a,const Node &b) {
if(a.dist<b.dist)
return a.dist>b.dist;
else if(b.dist==a.dist && b.cost>=a.cost)
return b.cost<a.cost;
}