题目描述
“您的个人假期”旅行社组织了一次比荷卢经济联盟的巴士之旅。
比荷卢经济联盟有很多公交线路。
每天公共汽车都会从一座城市开往另一座城市。
沿途汽车可能会在一些城市(零或更多)停靠。
旅行社计划旅途从 S 城市出发,到 F 城市结束。
由于不同旅客的景点偏好不同,所以为了迎合更多旅客,旅行社将为客户提供多种不同线路。
游客可以选择的行进路线有所限制,要么满足所选路线总路程为 S 到 F 的最小路程,要么满足所选路线总路程仅比最小路程多一个单位长度。
如上图所示,如果 S=1,F=5,则这里有两条最短路线 1→2→5,1→3→5,长度为 6;有一条比最短路程多一个单位长度的路线 1→3→4→5,长度为 7。
现在给定比荷卢经济联盟的公交路线图以及两个城市 S 和 F,请你求出旅行社最多可以为旅客提供多少种不同的满足限制条件的线路。
题解
这是一道裸的最短路,需要在最短路的模板上加一些小小的操作
求最短路的同时去记录次短路,并额外开一个数组记录最短路和次短路的总条数,这些操作在跑最短路的过程中都是很好进行的
具体讲一下转移过程
1.当这条路径比最短路小,将最短路的条数和长度转移给次短路,并更新最短路的条数和长度
2.当这条路径和最短路一样长,那就将最短路的条数增加
3.当这条路径比次短路小,更新次短路的条数和长度
4.当这条路径和次短路一样长,那就将次短路的条数增加
注意,上述条件均需满足if else 关系,如果没有else,那么就会将最短路和次短路混为一谈
我们需要求得的是最短路的条数和比最短路距离仅大1的路径条数
如果存在比最短路距离仅大1的路径,那么它一定会作为次短路
我们只需要判断一下次短路是不是这样的一条仅比最短路距离大1 的路径
如果是就加上次短路的路径条数即可
code
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
const int M=100100;
int n,m,s,t;
struct Star
{
int nxt,val,to;
}edge[M];
int head[N],tot=0;
void Lian(int x,int y,int z)
{
tot++;
edge[tot].nxt=head[x];
edge[tot].to=y;
edge[tot].val=z;
head[x]=tot;
}
struct Point
{
int dd,p,type;
bool operator<(const Point &x) const{
return dd>x.dd;
}
};
int dis[N][2],vis[N][2],cnt[N][2];
void dijkstra()
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
Point a;
a.dd=0;a.p=s;a.type=0;
dis[s][0]=0;
cnt[s][0]=1;
priority_queue <Point> q;
q.push(a);
while(!q.empty())
{
a=q.top();
q.pop();
int x=a.p,f=a.type;
if(vis[x][f]) continue;
vis[x][f]=1;
for(int i=head[x];i;i=edge[i].nxt)
{
int y=edge[i].to;
if(dis[y][0]>dis[x][f]+edge[i].val)
{
dis[y][1]=dis[y][0];
cnt[y][1]=cnt[y][0];
a.dd=dis[y][1],a.p=y,a.type=1;
q.push(a);
dis[y][0]=dis[x][f]+edge[i].val;
cnt[y][0]=cnt[x][f];
a.dd=dis[y][0],a.p=y,a.type=0;
q.push(a);
}
else if(dis[y][0]==dis[x][f]+edge[i].val) cnt[y][0]+=cnt[x][f];
else if(dis[y][1]>dis[x][f]+edge[i].val)
{
dis[y][1]=dis[x][f]+edge[i].val;
cnt[y][1]=cnt[x][f];
a.dd=dis[y][1],a.p=y,a.type=1;
q.push(a);
}
else if(dis[y][1]==dis[x][f]+edge[i].val) cnt[y][1]+=cnt[x][f];
}
}
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>m;
memset(head,0,sizeof(head));
for(int i=1;i<=m;i++)
{
int a,b,l;
cin>>a>>b>>l;
Lian(a,b,l);
}
cin>>s>>t;
dijkstra();
int ans=cnt[t][0];
if(dis[t][1]-1==dis[t][0]) ans+=cnt[t][1];
cout<<ans<<endl;
}
return 0;
}