最短路径问题
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
Input
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)
Output
输出 一行有两个数, 最短距离及其花费。
Sample Input
3 2
1 2 5 6
2 3 4 5
1 3
0 0
Sample Output
9 11
多权值最短路,用Dijkstra的优化版本,根据不同权值改改优先级队列的运算符重载
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
struct node{
int v,d,p;
node(){}
node(int vv,int dd,int pp){
v=vv;
d=dd;
p=pp;
}
};
struct Node{
int u,d,p;
Node(){}
Node(int uu,int dd,int pp){
u=uu;
d=dd;
p=pp;
}
bool operator<(const Node other)const{
if(d!=other.d) return d>other.d;//距离短的优先
else return p>other.p;//如果距离一样,花费少的优先
}
};
const int maxn=1005;
const int Inf=0x3f3f3f3f;
int n,m,s,t;
vector<node> G[maxn];
bool book[maxn];
int dis[maxn],cost[maxn];
void Dijkstra(){
priority_queue<Node> q;
for(int i=1;i<=n;i++){
dis[i]=Inf,cost[i]=Inf;
book[i]=false;
}
dis[s]=0,cost[s]=0;
q.push(Node(s,dis[s],cost[s]));
while(!q.empty()){
Node temp=q.top();
q.pop();
int u=temp.u;
if(book[u]) continue;
book[u]=true;
for(int i=0;i<G[u].size();i++){
node tmp=G[u][i];
int v=tmp.v;
int d=tmp.d;
int p=tmp.p;
if(dis[v]>dis[u]+d){
dis[v]=dis[u]+d;
cost[v]=cost[u]+p;
q.push(Node(v,dis[v],cost[v]));
continue;
}
if(dis[v]==dis[u]+d&&cost[v]>cost[u]+p){
cost[v]=cost[u]+p;
q.push(Node(v,dis[v],cost[v]));
}
}
}
printf("%d %d\n",dis[t],cost[t]);
}
int main(){
int a,b,d,p;
while(scanf("%d%d",&n,&m)){
if(n==0&&m==0) break;
for(int i=1;i<=n;i++)
G[i].clear();
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&a,&b,&d,&p);
G[a].push_back(node(b,d,p));
G[b].push_back(node(a,d,p));
}
scanf("%d%d",&s,&t);
Dijkstra();
}
return 0;
}