1577: 求最短距离及其花费
时间限制: 6 Sec
内存限制: 33 MB
提交: 490
解决: 139
题目描述
由n个点和m条无向边构成的无向连通图,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
输入
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t; 起点s,终点t。
(2<=n<=1000, n-1<=m<=100000, s != t)
输出
输出 一行有两个数, 最短距离及其花费。
样例输入
3 2 1 2 5 6 2 3 4 5 1 3
样例输出
9 11
提示
本题是一个求最短路径的题目。首选Dijkstra算法,也可用Floyd算法!
来自紫书361页的模板,优化后的复杂度m*log(n)
#include<vector>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iostream>
#include<queue>
#define INF 0x3f3f3f3f
#define MT(x,i) memset(x,i,sizeof(x))
using namespace std;
const int MAX = 1005;
struct HeapNode{ //优先队列的节点
int d,u,c;
bool operator<(const HeapNode& rhs)const{
if(d==rhs.d) return c>rhs.c;
else return d>rhs.d;
}
};
struct Edge{ //建图的边
int from,to,dist,cost;
Edge(int u,int v,int d,int c):from(u),to(v),dist(d),cost(c){}
};
struct Dijkstra{
int n,m;
vector<Edge>edges;//边
vector<int>G[MAX];//存储边的编号
bool done[MAX];//是否已永久标记
int d[MAX];//dist距离
int c[MAX];//cost花费
int p[MAX];//上一条
void init(int n){
this->n=n;//this->m=m;
for(int i=0;i<=n;++i) G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int dist,int cost){
edges.push_back(Edge(from,to,dist,cost));
m=edges.size();
G[from].push_back(m-1);
}
void dijkstra(int s){
priority_queue<HeapNode>Q;
for(int i=0;i<=n;i++) d[i]=INF;
d[s]=0,c[s]=0;
MT(done,0);
Q.push((HeapNode){0,s,0});
while(!Q.empty()){
HeapNode x = Q.top(); Q.pop();
int u=x.u;
if(done[u]) continue;
done[u]=true;
for(int i=0;i<G[u].size();++i ){
Edge& e=edges[G[u][i]];
if(d[e.to]>d[u]+e.dist ||(d[e.to]==d[u]+e.dist&&c[e.to]>c[u]+e.cost) ){
d[e.to]=d[u]+e.dist;
c[e.to]=c[u]+e.cost;
p[e.to]=G[u][i];
Q.push((HeapNode){d[e.to],e.to,c[e.to]} );
}
}
}
}
};
Dijkstra dij;
int main()
{
//freopen("F:\\1.txt","r",stdin);
int N,M,a,b,d,c,s,t;
while(~scanf("%d%d",&N,&M)){
dij.init(N);
for(int i=0;i<M;++i){
scanf("%d%d%d%d",&a,&b,&d,&c); a--;b--;
dij.AddEdge(a,b,d,c);
dij.AddEdge(b,a,d,c);
}
scanf("%d%d",&s,&t); s--;t--;
dij.dijkstra(s);
printf("%d %d\n",dij.d[t],dij.c[t]);
}
return 0;
}