给定n个点和m条有向边,(n<=2000,m<=n*(n-1)),求1到n的最短路长度和个数.
本题都是蓝题,为什么这题是绿题?洛咕的随意评分啊.
分析:(n<=2000),直接开邻接矩阵存图就好了,而且比较方便处理重边.然后跑dij,更新最短路的同时,记录一个(ans[i])表示起点1到i的最短路径条数.初始化(ans[1]=1),然后如果是松弛的更新(ans[v]=ans[u]),如果是正好相等则(ans[v]+=ans[u]).
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=2005;
int n,m,dis[N],ans[N],visit[N],w[N][N];
priority_queue<pair<int,int> >q;
inline void dij(){
for(int i=2;i<=n;++i)dis[i]=1e9;
q.push(pair<int,int>(0,1));
while(q.size()){
int u=q.top().second;q.pop();
if(visit[u])continue;visit[u]=1;
for(int v=1;v<=n;++v){
if(w[u][v]){
if(dis[v]>dis[u]+w[u][v]){
dis[v]=dis[u]+w[u][v];
ans[v]=ans[u];
q.push(pair<int,int>(-dis[v],v));
}
else if(dis[v]==dis[u]+w[u][v]){
ans[v]+=ans[u];
}
}
}
}
}
int main(){
n=read();m=read();
for(int i=1;i<=m;++i){
int a=read(),b=read(),c=read();
if(!w[a][b])w[a][b]=c;
else w[a][b]=min(w[a][b],c);
}
ans[1]=1;dij();
if(dis[n]==1e9)puts("No answer");
else printf("%d %d
",dis[n],ans[n]);
return 0;
}