D100 最短路条数 Dijkstra 算法 P1608 路径统计

D100 最短路条数 Dijkstra 算法 P1608 路径统计_哔哩哔哩_bilibili

 

P1608 路径统计 - 洛谷

给一个有权有向图(有重边),求 1 到 n 的最短路和最短路条数。统计条数要求经过的点的编号序列不同。

思路

首先,输入时需要去重边

主要看怎样统计最短路条数?

(1)如果 $d[v]>d[u]+w$,距离可以变短,那么最短路条数不增加,$cnt[v]=cnt[u]$

(2)如果 $d[v]=d[u]+w$,距离保持不变,那么最短路条数增加,$cnt[v]=cnt[v]+cnt[u]$

图中,4 到 6 的更新属于第(1)种,5 到 6 的更新属于第(2)种

相关板子:

D02【模板】最短路 Dijkstra 算法 P4779 单源最短路径 - 董晓 - 博客园 

 

// 最短路条数 Dijkstra 算法 O(MlogN)
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;

const int N=2010,M=4e6;
int h[N],to[M],ww[M],ne[M],idx;
void add(int a,int b,int c){
  to[++idx]=b,ww[idx]=c,ne[idx]=h[a],h[a]=idx;
}
int n,m,g[N][N];
int d[N],cnt[N];
bool vis[N];

void dijkstra(){
  memset(d,0x3f,sizeof d); d[1]=0; cnt[1]=1;
  priority_queue<pii,vector<pii>,greater<pii> > q; 
  q.push({0,1});
  while(!q.empty()){
    int u=q.top().second; q.pop();
    if(vis[u])continue; vis[u]=1;
    for(int i=h[u];i;i=ne[i]){
      int v=to[i],w=ww[i];
      if(d[v]>d[u]+w){ //如果1到v的距离可以变小
        d[v]=d[u]+w;
        cnt[v]=cnt[u]; //那就继承最短路条数
        q.push({d[v],v});
      }
      else if(d[v]==d[u]+w){  //如果1到v的距离相等
        cnt[v]=cnt[v]+cnt[u]; //那就累加最短路条数
      }
    }
  }
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1,a,b,c;i<=m;i++){
    scanf("%d%d%d",&a,&b,&c);
    if(g[a][b]==c) continue; //去重边
    add(a,b,c); g[a][b]=c;
  }
  
  dijkstra();
  if(d[n]==0x3f3f3f3f)printf("No answer\n");
  else printf("%d %d\n",d[n],cnt[n]); 
}

 

P1144 最短路计数 - 洛谷

给一个边权为 1 的无向图,求从 1 号点到其他点的最短路的条数

思路

本题不需要去重边。边权均为 1,最短路算法退化为 BFS

 

// 最短路条数 BFS 算法 O(n+m)
#include<bits/stdc++.h>
using namespace std;

const int N=1e6+5,M=4e6+5,mod=100003;
int h[N],to[M],ne[M],idx;
void add(int a,int b){
  to[++idx]=b,ne[idx]=h[a],h[a]=idx;
}
int n,m;
int d[N],cnt[N];

void bfs(){
  memset(d,0x3f,sizeof d); d[1]=0;
  cnt[1]=1;
  queue<int> q; q.push(1);
  while(!q.empty()){
    int u=q.front();q.pop();
    for(int i=h[u];i;i=ne[i]){
      int v=to[i];
      if(d[v]>d[u]+1){
        d[v]=d[u]+1;
        cnt[v]=cnt[u];
        q.push(v);
      }
      else if(d[v]==d[u]+1){
        cnt[v]=(cnt[v]+cnt[u])%mod;
      }
    }
  }
}
int main(){
  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
  cin>>n>>m;
  for(int i=0,a,b;i<m;i++){
    cin>>a>>b;
    add(a,b),add(b,a);
  }
  bfs();
  for(int i=1;i<=n;i++)cout<<cnt[i]<<"\n";
}

 

posted @ 2026-03-05 20:41  董晓  阅读(85)  评论(0)    收藏  举报