洛谷P1608 路径计数 题目简介 题目分析

题目描述

给你一个N点M边的有向图,求第一个点到第n个点的最短路和最短路条数

题目分析

很明显直接Dijkstra求最短路,加一个最短路计数

如下:

if(dis[y]>dis[x]+edge[i].w){
		dis[y]=dis[x]+edge[i].w;
		ans[y]=ans[x];
}
else if(dis[y]==dis[x]+edge[i].w) ans[y]+=ans[x];

记住要删除重边,要不然计数会重复

上代码

#include<bits/stdc++.h>
#define re register
#define ll long long
using namespace std;
inline int read()
{
	ll k=1,sum=0;
	char c=getchar();
	for(;c<'0' || c>'9';c=getchar()) if(c=='-') k=-1;
	for(;c>='0' && c<='9';c=getchar()) sum=sum*10+c-'0';
	return sum*k;
}
const int N=2e3+10,E=4e6+10;
int n,e;
struct Edge{
	int to,nxt,w;
};
Edge edge[E<<1];
const int MOD=100003;
int head[N],cnt;
int dep[N];
int dis[N],ans[N];
bool vis[N];
int awsl[N][N];
struct New{
	int x,d;
	bool operator<(const New& qwq) const{
		return d>qwq.d;
	}
};
priority_queue<New> Q;
inline void Add(int x,int y,int w){
	edge[++cnt].to=y;
	edge[cnt].nxt=head[x];
	edge[cnt].w=w;
	head[x]=cnt;
}
inline void Dijkstra(){
	memset(dis,0x3f3f3f3f,sizeof(dis));
	dis[1]=0;ans[1]=1;
	Q.push((New){1,0});
	while(!Q.empty()){
		New fr=Q.top();Q.pop();
		int x=fr.x;
		if(vis[x]) continue;
		vis[x]=1;
		for(re int i=head[x];i;i=edge[i].nxt){
			int y=edge[i].to;
			if(dis[y]>dis[x]+edge[i].w){
				dis[y]=dis[x]+edge[i].w;
				ans[y]=ans[x];
				Q.push((New){y,dis[y]});
			}
			else if(dis[y]==dis[x]+edge[i].w) ans[y]+=ans[x];
		}
	}
}
int main()
{
	n=read();e=read();
	for(re int i=1;i<=e;++i){
		int x=read(),y=read(),w=read();
		if(!awsl[x][y] || awsl[x][y]>w){
			Add(x,y,w);awsl[x][y]=w;
		}
	}
	Dijkstra();
	if(ans[n]==0) cout<<"No answer";
	else cout<<dis[n]<<" "<<ans[n];
	return 0;
}