题意:找出从S到F两个点之间的最短路和比最短路长1的次短路的条数之和。
分析:最短路很好求,关键是次短路,郁闷呀
不过,如果对最短路的更新距离的过程有更深的认识的话,就好办很多了。
用一个二维数组记录每一个节点距离起始点的最短距离和次短距离,再开一个二维数组记录路径数
更新状态时:
1)新值小于最短路径长:更新最短路径长,计数;次短路径长,计数
2)新值等于最短路径长:更新最短路径计数
3)新值大于最短路径长,小于次短路径长:更新次短路径长,计数
4)新值等于次短路径长:更新次短路径计数
#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
const int maxn=1005,inf=1<<29;
struct edge{int to,cost;};
struct node
{
int s,dist,f;//顶点、顶点到起点距离、标记变量
friend bool operator <(node a,node b)
{
if(a.dist!=b.dist) return a.dist>b.dist;
return a.s>b.s;
}
};
vector<edge>G[maxn];
int dp[maxn][3];//dp[i][1]计i点到起点最短路的数量,dp[i][2]计i点到起点次短路的数量
int d[maxn][3];//d[i][1]计i点到起点最短路的长度,d[i][2]计i点到起点次短路的长度
int vis[maxn][3];
int n,m,s,e;
void Dijkstra()
{
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
fill(&d[0][0],&d[maxn][0],inf);
priority_queue<node>q;
node now,t;
now.s=s;now.dist=0;now.f=1;
d[s][1]=0;dp[s][1]=1;
q.push(now);
while(q.size())
{
now=q.top();q.pop();
if(vis[now.s][now.f]) continue;
vis[now.s][now.f]=1;
for(int i=0;i<G[now.s].size();i++)
{
int v=G[now.s][i].to,w=G[now.s][i].cost;
if(!vis[v][1]&&d[v][1]>now.dist+w)// 1)新值小于最短路径长:更新最短路径长,计数;次短路径长,计数
{
if(d[v][1]!=inf)
{
t.s=v;t.f=2;t.dist=d[v][1];
d[v][2]=d[v][1];
dp[v][2]=dp[v][1];
q.push(t);
}
t.s=v;t.f=1;t.dist=now.dist+w;
d[v][1]=t.dist;
dp[v][1]=dp[now.s][now.f];
q.push(t);
}
else if(!vis[v][1]&&d[v][1]==now.dist+w) dp[v][1]+=dp[now.s][now.f];//2)新值等于最短路径长:更新最短路径计数
else if(!vis[v][2]&&d[v][2]>now.dist+w)// 3)新值大于最短路径长,小于次短路径长:更新次短路径长,计数
{
t.s=v;t.f=2;t.dist=now.dist+w;
d[v][2]=t.dist;
dp[v][2]=dp[now.s][now.f];
q.push(t);
}
else if(!vis[v][2]&&d[v][2]==now.dist+w) dp[v][2]+=dp[now.s][now.f];//4)新值等于次短路径长:更新次短路径计数
}
}
}
int main()
{
int Case;
scanf("%d",&Case);
while(Case--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++) G[i].clear();
for(int i=0;i<m;i++)
{
edge t;
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
t.to=b;t.cost=w;
G[a].push_back(t);
}
scanf("%d%d",&s,&e);
Dijkstra();
if(d[e][2]==d[e][1]+1) printf("%d\n",dp[e][2]+dp[e][1]);
else printf("%d\n",dp[e][1]);
}
return 0;
}