双调路径

试题描述
如今的道路收费发展很快。道路的密度越来越大,因此选择最佳路径是很现实的问题。城市的道路是双向的,每条道路有固定的旅行时间以及需要支付的费用。
路径是连续经过的道路组成的。总时间是各条道路旅行时间的和,总费用是各条道路所支付费用的总和。一条路径越快,或者费用越低,该路径就越好。严格地说,如果一条路径比别的路径更快,而且不需要支付更多费用,它就比较好。反过来也如此理解。如果没有一条路径比某路径更好,则该路径被称为最小路径。
这样的最小的路径有可能不止一条,或者根本不存在路径。

问题:读入网络,计算最小路径的总数。费用时间都相同的两条最小路径只算作一条。你只要输出不同种类的最小路径数即可。

输入
第一行有四个整数,城市总数 n,道路总数 m,起点和终点城市 s,e;
接下来的 m 行每行描述了一条道路的信息,包括四个整数,两个端点 p,r,费用 c,以及时间 t;
两个城市之间可能有多条路径连接。
输出
仅一个数,表示最小路径的总数。
输入示例
4 5 1 4
2 1 2 1
3 4 3 1
2 3 1 2
3 1 1 4
2 4 2 4
输出示例
2
其他说明
样例说明
样例输入如上图:
从 1 到 4 有 4 条路径。为 1→2→4(费用为 4,时间为 5),1→3→4(费用为 4,时间为 5),1→2→3→4(费用为 6,时间为 4),1→3→2→4(费用为 4,时间为 10)。
1→3→4和 1→2→4比 1→3→2→4 更好。有两种最佳路径:费用为 4,时间为 5(1→2→4 和 1→3→4 )费用为 6,时间为 4(1→2→3→4)。
数据范围与提示
对于全部数据,1≤n≤100,0≤m≤300,1≤s,e,p,r≤n,0≤c,t≤100,保证 s≠e,p≠r。

 很明显,这是一道最短路的题目

但是有两个状态

所以我们不能直接开数组

要把一个状态存在树祖中,另一个为下标

因为我们知道一条路径为最优的情况只有当它的一个指标大于另一个最优路径且它的另一个指标小于那条路径(否则另外一条路径就不是最优解了)

由此可得,最优解的集合中两个指标分别呈上升和下降趋势

从而推导出求解公式(详情看代码)

下面给出代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
int rd()
{
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
void write(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
    return ;
}
int n,m;
int s,end;
int head[100006],nxt[100006],to[100006];
int v[100006],t[100006];
int total=0;
void add(int x,int y,int a,int b)//邻接表存边 
{
    total++;
    v[total]=a;
    t[total]=b;
    to[total]=y;
    nxt[total]=head[x];
    head[x]=total;
    return ;
}
long long f[106][301*101];//f[i][j]代表到第i个点的费用为j时的最小时间 
int book[106][301*101];
queue <int> q;
queue <int> qq;
void spfa()//SPFA模板 
{
    book[s][0]=1;
    q.push(s);
    qq.push(0);
    f[s][0]=0;
    while(!q.empty())
    {
        int h=q.front(),hh=qq.front();
        q.pop();
        qq.pop();
        if(hh>m*101) continue;
        book[h][hh]=0;
        for(int e=head[h];e;e=nxt[e])
        {
            if(f[to[e]][hh+v[e]]>f[h][hh]+t[e])
            {
                f[to[e]][hh+v[e]]=f[h][hh]+t[e];
                if(!book[to[e]][hh+v[e]])
                {
                    book[to[e]][hh+v[e]]=1;
                    q.push(to[e]);
                    qq.push(hh+v[e]);
                }
            }
        }
    }
    return ;
}
int main()
{
    n=rd();
    m=rd();
    s=rd();
    end=rd(); int sum=0;
    for(int i=1;i<=m;i++)
    {
        int x,y,a,b;
        x=rd();
        y=rd();
        a=rd();
        b=rd();
        add(x,y,a,b);
        add(y,x,a,b);
        sum+=b;
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<=sum;j++)
            f[i][j]=99999999;
    }
    int set=f[1][0];
    spfa();
    int ans=0;
    for(int i=0;i<=sum;i++)
    {
        if(f[end][i]>=set) continue;//如果一条路径是最优情况,当它的费用大于上一条最优解时,它的时间必须小于上一条最优解 
        set=f[end][i];
        ans++;
    }
    printf("%d",ans);
    return 0;
}
蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
原文地址:https://www.cnblogs.com/WWHHTT/p/9621530.html