1. 程式人生 > 實用技巧 >最短路徑2+記錄所有最短路徑+求最短路徑的條數+重邊問題

最短路徑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;
	}
}