HDU 1688 Sightseeing (次短路计数)
题目传送门
题目大意
求\(s\)到\(t\)的最短路条数加上比最短路大1的路径条数\((1\leq n\leq 10^3,1\leq m\leq 10^4,1\leq L\leq 10^3,0\leq ans\leq10^9)(\)单向边\()\)。
Solution
最短路计数与次短路计数的模板题,只要注意判断一下次短路是否正好为最短路\(+1\)即可。
每次取队首元素来松弛最短路和次短路,注意只有松弛最短路失败时才松弛次短路,具体见代码。
注意每次d数组更新都要入队
因为是多组数据,别忘了重置cnt以及其他数组。
#include<bits/stdc++.h>
using namespace std;
#define maxn1 1005
#define maxn2 10005
#define INF 0x3f3f3f3f
int T;
template<typename T>void read(T& x){
int f=0;x=0;char ch=getchar();
while(ch<'0'||ch>'9'){f|=(ch=='-');ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
if(f)x=-x;
}
int head[maxn1],to[maxn2],nxt[maxn2],w[maxn2],cnt=0;
void add(int u,int v,int ww){
nxt[++cnt]=head[u];
to[cnt]=v;
w[cnt]=ww;
head[u]=cnt;
}
struct node{
int d,x,flag;
node(int d,int x,int flag):d(d),x(x),flag(flag){}
bool operator < (const node& a)const{
return d>a.d;
}
};
int d[maxn1][2],vis[maxn1][2],num[maxn1][2];
int dij(int s,int t){
memset(d,INF,sizeof(d));
memset(num,0,sizeof(num));
memset(vis,0,sizeof(vis));
priority_queue<node>q;
d[s][0]=0;
num[s][0]=1;
q.push(node(0,s,0));
while(!q.empty()){
int u=q.top().x,flag=q.top().flag;
q.pop();
if(vis[u][flag])continue;
vis[u][flag]=1;
for(int i=head[u];i!=-1;i=nxt[i]){
int v=to[i];
if(d[v][0]>d[u][flag]+w[i]){
if(d[v][0]!=INF){//一个小优化
d[v][1]=d[v][0];
num[v][1]=num[v][0];
q.push(node(d[v][1],v,1));//每次d数组更新都要入队
}
d[v][0]=d[u][flag]+w[i];
num[v][0]=num[u][flag];
q.push(node(d[v][0],v,0));
}else if(d[v][0]==d[u][flag]+w[i]){
num[v][0]+=num[u][flag];
}else if(d[v][1]>d[u][flag]+w[i]){
d[v][1]=d[u][flag]+w[i];
num[v][1]=num[u][flag];
q.push(node(d[v][1],v,1));
}else if(d[v][1]==d[u][flag]+w[i]){
num[v][1]+=num[u][flag];
}
}
}
int ans=num[t][0];
if(d[t][1]==d[t][0]+1)
ans+=num[t][1];
return ans;
}
int main(){
read(T);
int n,m,s,t,u,v,ww;
while(T--){
read(n),read(m);
memset(head,-1,sizeof(head));
cnt=0; //别忘了重置cnt
for(int i=1;i<=m;++i){
read(u),read(v),read(ww);
add(u,v,ww);
}
read(s),read(t);
printf("%d\n",dij(s,t));
}
return 0;
}

浙公网安备 33010602011771号