D94 最短路径树 BFS 算法 CF1005F Berland and the Shortest Paths
D94 最短路径树 BFS 算法 CF1005F Berland and the Shortest Paths_哔哩哔哩_bilibili
CF1005F Berland and the Shortest Paths - 洛谷
给定一个 n 个点,m 条边的无向简单连通图,每条边权为 1,求最短路径树的方案数,并输出 k 种方案
思路
最短路计数问题,由于每个边的边权为 1 ,求最短路径树的 Dijkstra 算法退化为广搜(BFS)
一个点的所有前驱边都是平权的,所以对每个点维护一个前驱边的编号集 pre[v],
这样总的方案数就是所有点集合大小的乘积,然后用 DFS 在每个集合中选一个前驱边输出
图中节点 2,3 均有一条前驱边,节点 4,5 均有两条前驱边,所以方案数为 $1*1*2*2=4$
四种方案遍历回溯得出(红数字代表边的编号):111010,111001,110110,110101
如果方案数大于 k 值,直接取 k 种;如果方案数小于 k 值,搜完即终止

相关板子:
D92【模板】最短路径树 Dijkstra 算法 CF545E Paths and Trees - 董晓 - 博客园
// 最短路径树 BFS 算法 O(N+M) #include<bits/stdc++.h> using namespace std; const int N=2e5+5; int idx,h[N],to[N<<1],ne[N<<1],id[N<<1]; void add(int a,int b,int c){ to[++idx]=b;id[idx]=c;ne[idx]=h[a];h[a]=idx; } int n,m,k,sum,tot=1,d[N]; bool vis[N]; vector<int> pre[N]; void bfs(int s){ queue<int> q; q.push(s); d[s]=0; while(!q.empty()){ int u=q.front(); q.pop(); for(int i=h[u];i;i=ne[i]){ int v=to[i],w=id[i]; if(!d[v]){ d[v]=d[u]+1; pre[v].push_back(w); //保存v的前驱边编号 q.push(v); } else if(d[v]==d[u]+1) pre[v].push_back(w); } } } void dfs(int x){ //输出tot种方案 if(x==n+1){ for(int i=1;i<=m;++i)printf("%d",vis[i]); //输出方案 puts(""); if(++sum==tot) exit(0); return; } for(int i=0;i<pre[x].size();++i){ vis[pre[x][i]]=1; //选x的第i个前驱边 dfs(x+1); //枚举点2,3,4,...,n vis[pre[x][i]]=0; //不选 } } signed main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1,x,y;i<=m;++i){ scanf("%d%d",&x,&y); add(x,y,i),add(y,x,i); } bfs(1); for(int i=2;i<=n;++i){ if(tot*pre[i].size()>k){tot=k;break;} else tot*=pre[i].size(); } printf("%d\n",tot); //方案数 dfs(2); }
有边权的无向图,求最短路径树的方案数
思路
同样的思路,用 cnt[v] 记录节点的最短路方案数,最后乘起来就行了
// 最短路径树 Dijkstra 算法 O(MlogN) #include<bits/stdc++.h> #define ll long long #define pli pair<ll,int> using namespace std; const int N=1010,M=N*N; const ll mod=2147483647; int h[N],to[M],ne[M],idx; ll ww[M]; void add(int a,int b,ll c){ to[++idx]=b,ww[idx]=c,ne[idx]=h[a],h[a]=idx; } int n,m; ll d[N],cnt[N]; bool vis[N]; void dijkstra(){ for(int i=1; i<=n; i++) d[i]=1e18; d[1]=0; priority_queue<pli,vector<pli>,greater<pli> >q; q.push({0,1}); while(!q.empty()){ auto 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){ d[v]=d[u]+w; q.push({d[v],v}); cnt[v]=1; } else if(d[v]==d[u]+w) cnt[v]++; } } } int main(){ scanf("%d%d",&n,&m); for(int i=0; i<m; i++){ int a,b; ll c; scanf("%d%d%lld",&a,&b,&c); add(a,b,c),add(b,a,c); } dijkstra(); ll ans=1; for(int i=2; i<=n; i++) ans=ans*cnt[i]%mod; printf("%lld\n",ans); }
浙公网安备 33010602011771号