1. 程式人生 > >洛谷1144 最短路的個數

洛谷1144 最短路的個數

方法一:這種發放適合於只求最短路的個數,不能用來輸出最短路。

我們直接在spfa的過程中使用cnt[]陣列記錄最短路的個數,用dijkstra也可以!

更新cnt分情況:

 

  1. 如果dis[next]>dis[now]+1
    那麼之前到達點next的路>dis[now]+1
    cnt[next]=cnt[now]
  2. 如果dis[next]==dis[now]+1
    那麼之前到達點next的路也有距離為dis[now]+1的點。
    cnt[next]+=cnt[now]
#include <bits/stdc++.h> 
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define res register int 
const int maxn=1e6+5;
vector<int> v[maxn];
int dis[maxn],vis[maxn];
int cnt[maxn];
int N,M,mod=100003;


//最短路的個數
void spfa()
{
	memset(dis,inf,sizeof(dis));
	memset(vis,0,sizeof(vis));
	queue<int> q;
	q.push(1);
	vis[1]=1;
	dis[1]=0;
	cnt[1]=1;
	while(!q.empty()){
		int x=q.front();
		q.pop();
		vis[x]=0;
		for(res i=0;i<v[x].size();i++){
			int y=v[x][i];
			if(dis[y]>dis[x]+1){
				dis[y]=dis[x]+1;
				cnt[y]=cnt[x]%mod;
				if(!vis[y]){
					q.push(y);
					vis[y]=1;
				}
			}else if(dis[y]==dis[x]+1){
				cnt[y]+=cnt[x];
				cnt[y]%=mod;
				if(!vis[y]){
					q.push(y);
					vis[y]=1;
				}
			}
		} 
	}
} 

int main()
{
	scanf("%d%d",&N,&M);
	int from,to;
	for(res i=0;i<M;i++){
		scanf("%d%d",&from,&to);
		v[from].push_back(to);
		v[to].push_back(from);
	}
	spfa();
	for(res i=1;i<=N;i++){
		printf("%d",cnt[i]);
		printf("\n");
	}
	return 0;
}





方法二:可以記錄路徑,但是很慢 

我們可以用vector<int> pre[maxn]記錄下每一個節點被最短到達的前一個點的節點序號。因為我們記錄的都是前驅,所以我們可以從終點出發。這樣遍歷到的每一個節點都在最短路上面。然後我們dfs或者bfs,ans+每一個遍歷到節點前驅的個數-1。最後輸出讓ans+1。