路径统计

洛咕

给定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\n",dis[n],ans[n]);
    return 0;
}

posted on 2019-09-18 21:50  PPXppx  阅读(151)  评论(0)    收藏  举报