SDNU_ACM_ICPC_2020_Winter_Practice_2nd B 双权值最短路

题目

给你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;
}

发布了46 篇原创文章 · 获赞 0 · 访问量 1156

猜你喜欢

转载自blog.csdn.net/weixin_45719073/article/details/104077210