题目
给你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
考察的是双权值最短路,注意此题为无向图
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#define re register
using namespace std;
const int maxn=2002;
const int maxm=200005;
const int inf=0x3f3f3f3f;
int n,m,st,en,cnt,dis[maxn];///cnt 总边数
int head[maxn],vis[maxn],times[maxn],mm[maxn];///距离数组
///head 是第几边,vis 是否在更新数组,times 判断负环,mm 花费数组
inline int read()
{
int x=0,w=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')w=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
return x*w;
}
struct edge
{
int u,v,w,p,ne;
} ed[maxm];
void init()
{
for(int i=0;i<=n;i++)
{
head[i]=-1;
dis[i]=inf,mm[i]=inf;
times[i]=0,vis[i]=0;
}
cnt=0;///总边数
}
void addedge(int u,int v,int w,int p)
{
ed[cnt].u=u;
ed[cnt].v=v;
ed[cnt].w=w;
ed[cnt].p=p;
ed[cnt].ne=head[u];///u点的上一条边的编号
head[u]=cnt++;///更新u点边的编号///第一条边的编号为0
}
struct cmp
{
bool operator()(int a,int b)
{
return dis[a]>dis[b];///按dis[i]的值从小往大排序
}
};///优化 找离这个点最近的点
bool spfa(int st)
{
priority_queue<int,vector<int>,cmp>q;
q.push(st);///放入队列
vis[st]=1;///标记
dis[st]=0;///到初始点的距离为0
mm[st]=0;///到初始点的花费为0
while(!q.empty())
{
int u=q.top();
q.pop();
vis[u]=0;///取消标记
for(int i=head[u];i!=-1;i=ed[i].ne)
{
int v=ed[i].v;
if(dis[v]>dis[u]+ed[i].w)
{
dis[v]=dis[u]+ed[i].w;
mm[v]=mm[u]+ed[i].p;///更新
if(!vis[v])
{
vis[v]=1;
q.push(v);///标记并放入队列
if(++times[v]>n)
{
return 0;
}///判负环
}
}
else if (dis[v]==dis[u]+ed[i].w)
{
mm[v]=min(mm[v],mm[u]+ed[i].p);
}
}
}
return 1;
}
int main()
{
while(cin>>n>>m &&n!=0&&m!=0)
{
init();///初始化
for(int i=0;i<m;i++)
{
int u=read(),v=read(),w=read(),p=read();
addedge(u,v,w,p);
addedge(v,u,w,p); ///无向图要加这一句
}
st=read(),en=read();
spfa(st);
cout<<dis[en]<<" "<<mm[en]<<endl; ///输出到终点值的最短距离,最少花费
}
return 0;
}