rt,洛谷似乎没有
题目:给定一张包含n个点、m条边的有向图,并且给定起始点s和终点t,求从s到t的最短路线和比最短路线多一个单位距离的路线的总方案数。
我的思路:由于比最短路多一个单位距离路线的次短路只可能从更新他最短路的点转移而来,所以跑dijkstra求解
官方思路:跑最短路和次短路计数,如果次短路==最短路+1,输出次短路和最短路的方案数总和;否则输出最短路方案
不知道为啥0分。。。ToT
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int INF=998244353;
const int maxn=1003+5,maxm=1000006*2+5;;
int n,m; int s,t;
int dis[maxn]; long long ans0[maxn],ans1[maxn];
bool vis[maxn]; priority_queue<pair<int,int> >q;
int head[maxn]; int ver[maxm],nxt[maxm]; int edge[maxm]; int tot=0;
inline void add(int x,int y,int z)
{
tot++;
ver[tot]=y; edge[tot]=z;
nxt[tot]=head[x]; head[x]=tot;
return;
}
inline void dijk()
{
for(int i=1;i<=n;i++) vis[i]=false,dis[i]=INF;
dis[s]=0;
q.push(make_pair(0,s));
while(q.size())
{
int x=q.top().second; q.pop();
if(vis[x]==true) continue;
vis[x]=true;
for(int i=head[x];i;i=nxt[i])
{
int y=ver[i];
if(dis[y]>dis[x]+edge[i]) dis[y]=dis[x]+edge[i],q.push(make_pair(-dis[y],y));
}
}
return;
}
inline void count()
{
for(int i=1;i<=n;i++) vis[i]=false,ans0[i]=ans1[i]=0;
dis[s]=0; ans0[s]=1;
q.push(make_pair(0,s));
while(q.size())
{
int x=q.top().second; q.pop();
if(vis[x]==true) continue;
vis[x]=true;
for(int i=head[x];i;i=nxt[i])
{
int y=ver[i];
if(vis[y]) continue;
if(dis[y]==dis[x]+edge[i])
{
dis[y]=dis[x]+edge[i],q.push(make_pair(-dis[y],y));
ans0[y]+=ans0[x]; ans1[y]+=ans1[x];
}
else if(dis[y]+1==dis[x]+edge[i])
ans1[y]+=ans0[x];
}
}
return;
}
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
memset(dis,0,sizeof(dis));
memset(ans0,0,sizeof(ans0)),memset(ans1,0,sizeof(ans1));
memset(head,0,sizeof(head)); memset(ver,0,sizeof(ver)),memset(nxt,0,sizeof(nxt));
memset(edge,0,sizeof(edge));
tot=0; for(int i=1;i<=n;i++) head[i]=0;
while(m--)
{
int x,y,z; scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
scanf("%d%d",&s,&t);
dijk();
count();
printf("%lld\n",(ans0[t]+ans1[t]));
}
return 0;
}
码风不行,见谅QwQ