最短路径2+记录所有最短路径+求最短路径的条数+重边问题

最短路径2

ECNU-1818

  • 本题需要注意的一个问题就是重边的问题,虽然这题的数据量很小,但是不能使用邻接矩阵来存储,也不能将重边记为最小边来计算。
  • 这里求最短路径的条数有很多方法,我第一个想到的是使用dfs来遍历,但是会超时。
  • 有一个简单的记录最短路径条数的方法是使用一个num数组
/**
 * 这里不能用邻接矩阵的形式存储整个图,因为可能会出现重边的问题。
 * 如果是简单的重边,取最短边即可,但是本题需要求出所有的最短路径,所以更长的边
 * 对结果会有影响 
 */
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<map> 
#include<vector>
#include<unordered_map>
#include<bitset>
using namespace std;
const int INF=0X3F3F3F3F;
const int maxn=103;
const int maxm=3003;
int n,m;
int d[maxn];
bool flag[maxn];
int weight[maxn][maxn];
vector<int>pre[maxn];//记录所有的最短路径 
int ans;
void dijkstra(int s){
	for(int i=0;i<=n;i++){
		d[i]=INF;
	}
	d[s]=0;
	for(int y=1;y<=n;y++){
		int x=-1,mins=INF;
		for(int i=1;i<=n;i++){
			if(!flag[i]&&d[i]<=mins){
				mins=d[i];
				x=i;
			}
		}
		if(x==-1){
			continue;
		}
		flag[x]=true;
		for(int i=1;i<=n;i++){
			if(i==x)
				continue;
			if(d[i]>d[x]+weight[x][i]){
				d[i]=d[x]+weight[x][i];
				pre[i].clear();
				pre[i].push_back(x); 
			}else if(d[i]==d[x]+weight[x][i]){
				pre[i].push_back(x);
			}
		}
	}
}
void dfs(int cur){
	if(cur==1){//遍历到起点 
		ans++;
		return;
	}
	for(auto i:pre[cur]){
		dfs(i); //往前遍历 
	} 
}
int main(){
	cin>>n>>m;
	for(int i=0;i<=n;i++){
		for(int j=0;j<=n;j++){
			weight[i][j]=INF;
		}
		weight[i][i]=0;
	}
	for(int i=0;i<m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		weight[u][v]=min(weight[u][v],w);
	}
	dijkstra(1);
	ans=0;
	dfs(n);
	cout<<d[n]<<" "<<ans<<endl;
	return 0;
}
/**
 * 这里不能用邻接矩阵的形式存储整个图,因为可能会出现重边的问题。
 * 如果是简单的重边,取最短边即可,但是本题需要求出所有的最短路径,所以更长的边
 * 对结果会有影响 
 */
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<map> 
#include<vector>
#include<queue>
#include<unordered_map>
#include<bitset>
using namespace std;
const int INF=0X3F3F3F3F;
const int maxn=103;
const int maxm=3003;
int n,m;
int top;
int ans;
int head[maxn];
int d[maxn];
int num[maxn];
vector<int>pre[maxn];
struct Node{
	int to,dis;
	Node(){}
	Node(int a,int b):to(a),dis(b){}
	bool operator<(const Node& node)const{
		return dis>node.dis;
	}
};
struct Edge{
	int to;
	int next;
	int cost;
};
Edge edge[maxm];
void addEdge(int from,int to, int cost){
	edge[top].to=to;
	edge[top].next=head[from];
	edge[top].cost=cost;
	head[from]=top++;
}
void dijkstra(int s){
	num[s]=1;
//	memset(d,INF,sizeof(d));
	for(int i=0;i<=n;i++){
		d[i]=INF;
	}
	d[s]=0;
	priority_queue<Node> que;
	que.push(Node(s,0));
	while(!que.empty()){
		Node now=que.top();
		que.pop();
		if(d[now.to]<now.dis)
			continue;
		for(int i=head[now.to];i!=-1;i=edge[i].next){
			Edge e=edge[i];
			if(d[e.to]>d[now.to]+e.cost){
				d[e.to]=d[now.to]+e.cost;
				que.push(Node(e.to,d[e.to]));
				pre[e.to].clear();
				pre[e.to].push_back(now.to);
				num[e.to]=num[now.to];
			}else if(d[e.to]==d[now.to]+e.cost){
				pre[e.to].push_back(now.to);
				num[e.to]+=num[now.to];
			} 
		}
	}
}
void dfs(int cur){
	if(cur==1){//遍历到起点 
		ans++;
		return;
	}
	for(auto i:pre[cur]){
		dfs(i); //往前遍历 
	} 
}
int main(){
	cin>>n>>m;
	top=0;
	memset(head,-1,sizeof(head)); 
	for(int i=0;i<m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		addEdge(u,v,w);
	}
	dijkstra(1);
	ans=0;
	dfs(n);
	if(d[n]==INF){
		cout<<"-1 0"<<endl;
	}else {
		cout<<d[n]<<" "<<num[n]<<endl;
//		cout<<d[n]<<" "<<ans<<endl;
	}
} 
posted @ 2020-10-07 12:13  Garrett_Wale  阅读(514)  评论(0编辑  收藏  举报