analysis
最短路计数
注意当spfa中一个点计算完了后,一定要记得将它清零,否则会造成重复计算,如下图:
同时,记得处理重边,否则会导致路径数偏多(题目认为城市u,v之间所有等长的边都是同一条路)
code
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define ll int
#define isdegit(a) ((a>='0'&&a<='9'))
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(!isdegit(r)){if(r=='-')neg=-1;r=getchar();}
while(isdegit(r)){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
const int maxn=2000+10,maxm=maxn*maxn;
struct node{
int e;
int w;
int nxt;
}edge[maxm];
int n,m,cnt=0;
int head[maxn];
inline void addl(register int u,register int v,register int w){
edge[cnt].e=v;
edge[cnt].w=w;
edge[cnt].nxt=head[u];
head[u]=cnt++;
}
ll dis[maxn];
ll rot[maxn];
deque<int>q;
int Dis[maxn][maxn];
inline void spfa(register int u,register int to){
clean(dis,0x7f);
clean(rot,0);
dis[u]=0;
rot[u]=1;
q.push_front(u);
while(q.empty()==false){
int f=q.front();
q.pop_front();
if(f==to)
continue;
for(int i=head[f];i!=-1;i=edge[i].nxt){
int v=edge[i].e;
if(dis[v]>dis[f]+(ll)Dis[f][v]){
rot[v]=rot[f];
dis[v]=dis[f]+(ll)Dis[f][v];
if(!q.empty()&&dis[q.front()]>dis[v])
q.push_front(v);
else q.push_back(v);
}
else if(dis[v]==dis[f]+(ll)Dis[f][v]){
rot[v]+=rot[f];
q.push_back(v);
}
}
rot[f]=0;
}
if(dis[to]<0x7f7f7f7f)
printf("%d %d\n",dis[to],rot[to]);
else
printf("No answer\n");
}
int main(){
#ifndef ONLINE_JUDGE
freopen("dat.txt","r",stdin);
#endif
clean(head,-1);
clean(Dis,0x7f);
read(n);
read(m);
register int x,y,z;
loop(i,1,m){
read(x);read(y);read(z);
Dis[x][y]=min(Dis[x][y],z);
}
loop(i,1,n){
loop(j,1,n){
if(Dis[i][j]<0x7f7f7f7f){
addl(i,j,Dis[i][j]);
}
}
}
spfa(1,n);
return 0;
}