题目分析
这道题就是一道最短路的基础题,直接套模板就可以了,当然需要注意一点就是题目所说的如果存在多个最短路径需要找出花费最小的。这道题用了280MS,我已经用队列优化过了,可能用vector实现邻接表没有直接写邻接表快。
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int > pii;
const int maxn = 1005;
const int INF = 0x3f3f3f3f;
struct Edge
{
int to,dist,cost;
Edge(int t,int d,int c):to(t),dist(d),cost(c) {}
};
struct Dijkstra
{
vector <Edge> vec; //存边
vector <int> G[maxn]; //用vector存每个点的相邻顶点
int dist1[maxn],dist2[maxn]; //一个表示长度,一个表示花费
bool done[maxn]; //判重
void init(int n){
for(int i = 0; i <= n; i++)
G[i].clear();
vec.clear();
}
void addEdge(int from,int to,int dist,int cost){
vec.push_back(Edge(to,dist,cost));
G[from].push_back(vec.size()-1);
vec.push_back(Edge(from,dist,cost));
G[to].push_back(vec.size()-1);
}
//如果每个边的权重相同,那么直接用队列就可以了
void dijkstra(int s)
{
priority_queue <pii, vector<pii>, greater<pii> > pq; //花费小的先出队
memset(dist1, INF, sizeof(dist1));
memset(dist2, INF, sizeof(dist2));
memset(done,0,sizeof(done));
dist1[s] = dist2[s] = 0;
pq.push(pii(0,s));
while(!pq.empty())
{
pii pre = pq.top(); pq.pop();
int u = pre.second;
if(done[u]) continue;
done[u] = true;
for(int i = 0; i < (int)G[u].size(); i++)
{
Edge& e = vec[G[u][i]];
if(dist1[e.to] > dist1[u] + e.dist){
dist1[e.to] = dist1[u] + e.dist;
dist2[e.to] = dist2[u] + e.cost;
pq.push( pii(dist1[e.to], e.to) );
}
else if(dist1[e.to] == dist1[u] + e.dist) //注意相同的路径长度要求花费最小
dist2[e.to] = min( dist2[e.to], dist2[u] + e.cost);
}
}
}
}graph;
int main()
{
int n,m;
while(scanf("%d%d", &n, &m) != EOF){
if(!n && !m) break;
int a,b,d,p;
graph.init(n);
while(m--)
{
scanf("%d%d%d%d", &a, &b, &d, &p);
graph.addEdge(a,b,d,p);
}
scanf("%d%d", &a, &b);
graph.dijkstra(a);
printf("%d %d\n", graph.dist1[b], graph.dist2[b]);
}
return 0;
}