洛谷 P1608 路径统计

洛谷 P1608 路径统计

洛谷传送门

题目描述

“RP 餐厅” 的员工素质就是不一般,在齐刷刷的算出同一个电话号码之后,就准备让 HZH,TZY 去送快餐了,他们将自己居住的城市画了一张地图,已知在他们的地图上,有 NN 个地方,而且他们目前处在标注为 “1” 的小镇上,而送餐的地点在标注为 “N” 的小镇。(有点废话)除此之外还知道这些道路都是单向的,从小镇 II 到 JJ 需要花费 D[I, J]D[I,J] 的时间,为了更高效快捷的将快餐送到顾客手中,他们想走一条从小镇 11 到小镇 NN 花费最少的一条路,但是他们临出发前,撞到因为在路上堵车而生气的 FYY,深受启发,不能仅知道一条路线,万一。。。于是,他们邀请 FYY 一起来研究起了下一个问题:这个最少花费的路径有多少条?

输入格式

输入文件第一行为两个空格隔开的数 NN,EE,表示这张地图里有多少个小镇及有多少边的信息。

下面 EE 行,每行三个数 II、JJ、CC,表示从 II 小镇到 JJ 小镇有道路相连且花费为 CC.(注意,数据提供的边信息可能会重复,不过保证 I\not=JI=J,1 \leq I1≤I,J\leq NJN)。

输出格式

输出文件包含两个数,分别是最少花费和花费最少的路径的总数.

两个不同的最短路方案要求:路径长度相同(均为最短路长度)且至少有一条边不重合。

若城市 NN 无法到达则只输出一个 No answer


题解:

Dij求最短路+最短路计数。

最短路计数的博客请见:

浅谈最短路计数

代码:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=2010;
int n,e;
int mp[maxn][maxn];
int tot,head[maxn],nxt[maxn*maxn],to[maxn*maxn],val[maxn*maxn];
void add(int x,int y,int z)
{
	to[++tot]=y;
	val[tot]=z;
	nxt[tot]=head[x];
	head[x]=tot;
}
priority_queue<pair<int,int> >q;
int dist[maxn],cnt[maxn];
bool v[maxn];
void dijkstra()
{
	memset(dist,127,sizeof(dist));
	dist[1]=0;
	cnt[1]=1;
	q.push(make_pair(0,1));
	while(!q.empty())
	{
		int x=q.top().second;
		q.pop();
		if(v[x])
			continue;
		v[x]=1;
		for(int i=head[x];i;i=nxt[i])
		{
			int y=to[i];
			if(dist[x]+val[i]<dist[y])
			{
				dist[y]=dist[x]+val[i],cnt[y]=cnt[x];
				q.push(make_pair(-dist[y],y));
			}
			else if(dist[x]+val[i]==dist[y])
				cnt[y]+=cnt[x];
		}
	}
}
int main()
{	
	scanf("%d%d",&n,&e);
	for(int i=1;i<=e;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		if(!mp[x][y]||mp[x][y]>z)
		{
			add(x,y,z);
			mp[x][y]=z;
		}
	}
	dijkstra();
	if(dist[n]>1e9)
	{
		puts("No answer");
		return 0;
	}
	printf("%d %d",dist[n],cnt[n]);
	return 0;
}

posted @ 2020-11-03 18:24  Seaway-Fu  阅读(121)  评论(0编辑  收藏  举报