题意:
给定一张有向图,求图中的最短路和比最短路长度大1的路径的条数
分析:
感觉这道题诠释了dijkstra算法的精髓,(⊙o⊙)…
dis[i][0]代表i点到s的最短路径,dis[i][1]代表i到s的次短路
num[i][0]&num[i][1]同理,vis[i][0]&vis[i][1]同理
当我们在求最短路的时候,每次取队首来更新与他相连的节点的最短路径,求次短路同理
当tmp(队首的更新值)小于最短路时,更新最短路和次短路
等于最短路时更新最短路数量
大于最短路小于次短路时更新次短路
等于次短路时更新次短路数量
代码如下:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1000+5,maxm=10000+5;
int cas,n,m,s,e,cnt,hd[maxn],to[maxm],nxt[maxm],w[maxm],dis[maxn][2],num[maxn][2];
bool vis[maxn][2];
struct lala{
int id,flag;
lala(int idd,int f){
id=idd,flag=f;
}
friend bool operator < (lala a,lala b){
return dis[a.id][a.flag]>dis[b.id][b.flag];
}
};
inline int read(){
char ch=getchar();
int f=1,x=0;
while(!(ch>='0'&&ch<='9')){
if(ch=='-')
ch=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
x=x*10+ch-'0',ch=getchar();
return f*x;
}
void add(int x,int y,int z){
to[cnt]=y;
w[cnt]=z;
nxt[cnt]=hd[x];
hd[x]=cnt++;
}
void dijkstra(){
priority_queue<lala> pq;
dis[s][0]=0,num[s][0]=1,pq.push(lala(s,0));
while(!pq.empty()){
lala top=pq.top();
pq.pop();
int u=top.id,flag=top.flag;
if(vis[u][flag])
continue;
vis[u][flag]=true;
for(int i=hd[u];i!=-1;i=nxt[i]){
int v=to[i],lalala=dis[u][flag]+w[i];
if(lalala<dis[v][0]){
if(dis[v][0]!=inf)
dis[v][1]=dis[v][0],num[v][1]=num[v][0],pq.push(lala(v,1));
dis[v][0]=lalala,num[v][0]=num[u][flag],pq.push(lala(v,0));
}
else if(lalala==dis[v][0])
num[v][0]+=num[u][flag];
else if(lalala<dis[v][1])
dis[v][1]=lalala,num[v][1]=num[u][flag],pq.push(lala(v,1)) ;
else if(lalala==dis[v][1])
num[v][1]+=num[u][flag];
}
}
}
signed main(void){
cas=read();
while(cas--){
n=read(),m=read();
memset(hd,-1,sizeof(hd)),cnt=0;
memset(vis,false,sizeof(vis));
memset(dis,inf,sizeof(dis));
memset(num,0,sizeof(num));
for(int i=1,x,y,z;i<=m;i++)
x=read(),y=read(),z=read(),add(x,y,z);
s=read(),e=read();
dijkstra();
int ans=num[e][0];
if(dis[e][1]-1==dis[e][0])
ans+=num[e][1];
cout<<ans<<endl;
}
return 0;
}
by >o< neighthorn