【图论】最短路计数

题目链接: https://atcoder.jp/contests/abc211/tasks/abc211_d

题目:

思路:

根据dijkstra松弛操作,如果d[v]==d[u]+1,那么u是v的最短路的必经之路,那么v的最短路条数一部分就是到u的最短路条数。

代码:

bfs

// Problem: D - Number of Shortest paths
// Contest: AtCoder - AtCoder Beginner Contest 211
// URL: https://atcoder.jp/contests/abc211/tasks/abc211_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>

using namespace std;
#define int long long
typedef pair<int,int> pii;

const int N = 2e5+5;
const int mod=1e9+7;

int n,m;
vector<int> e[N];
int d[N];
int ans[N];

void bfs(){
	queue<int> q;
	q.push(1);
	ans[1]=1;
	d[1]=0;
	
	while(!q.empty()){
		auto u=q.front();
		q.pop();
		
		for(auto v:e[u]){
			//由于权值都为1,第一次搜到时就是最小值
			if(d[v]==-1){
				d[v]=d[u]+1;
				q.push(v);
			}
			if(d[v]==d[u]+1){
				ans[v]=(ans[v]+ans[u])%mod;
			}
		}
	}
	cout<<ans[n]%mod<<"\n";
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		d[i]=-1;
	}
	bfs();
	
	
	return 0;	

}




dijkstra

// Problem: D - Number of Shortest paths
// Contest: AtCoder - AtCoder Beginner Contest 211
// URL: https://atcoder.jp/contests/abc211/tasks/abc211_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>

using namespace std;
#define int long long
typedef pair<int,int> pii;

const int N = 2e6+5;
const int mod=1e9+7;

int n,m;
vector<int> e[N];
int d[N],s[N];
bool st[N];

void dijkstra(){
	d[1]=0,s[1]=1;
	priority_queue<pii,vector<pii>,greater<pii>> q;
	q.push({0,1});
	
	while(!q.empty()){
		auto t=q.top();
		q.pop();
		
		if(st[t.second]) continue;
		st[t.second]=1;
		
		for(auto v:e[t.second]){
			if(d[v]>d[t.second]+1){
				d[v]=d[t.second]+1;
				q.push({d[v],v});
				s[v]=s[t.second];
				s[v]=s[v]%mod;
			}
			else if(d[v]==d[t.second]+1){
				s[v]+=s[t.second];
				s[v]=s[v]%mod;
			}
		}
	}
	cout<<s[n]<<"\n";
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		d[i]=1e15;
		st[i]=0;
	}
	dijkstra();
	
	
	return 0;	

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值