P1144 最短路计数
最短路计数
题目描述
给出一个 \(N\) 个顶点 \(M\) 条边的无向无权图,顶点编号为 \(1\sim N\)。问从顶点 \(1\) 开始,到其他每个点的最短路有几条。
输入格式
第一行包含 \(2\) 个正整数 \(N,M\),为图的顶点数与边数。
接下来 \(M\) 行,每行 \(2\) 个正整数 \(x,y\),表示有一条由顶点 \(x\) 连向顶点 \(y\) 的边,请注意可能有自环与重边。
输出格式
共 \(N\) 行,每行一个非负整数,第 \(i\) 行输出从顶点 \(1\) 到顶点 \(i\) 有多少条不同的最短路,由于答案有可能会很大,你只需要输出 $ ans \bmod 100003$ 后的结果即可。如果无法到达顶点 \(i\) 则输出 \(0\)。
样例 #1
样例输入 #1
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
样例输出 #1
1
1
1
2
4
提示
\(1\) 到 \(5\) 的最短路有 \(4\) 条,分别为 \(2\) 条 \(1\to 2\to 4\to 5\) 和 \(2\) 条 \(1\to 3\to 4\to 5\)(由于 \(4\to 5\) 的边有 \(2\) 条)。
对于 \(20\%\) 的数据,\(1\le N \le 100\);
对于 \(60\%\) 的数据,\(1\le N \le 10^3\);
对于 \(100\%\) 的数据,\(1\le N\le10^6\),\(1\le M\le 2\times 10^6\)。
dijkstra+堆优化
统计路径用的最low的方法 两边dijkstra……
其实也无妨 做出来即可 反正复制粘贴也没多大码量
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5,M=2e6+5;
const int inf=1e15;
const int MOD=100003;
int m,n;
struct Graph {
int nxt,to;
} edge[M<<1];
int head[M],cnt;
int dis[N],num[N],dis2[N];
struct did {
int u,d;
bool operator < (const did& t)const {
return t.d<d;
}
};
inline void add(int u,int v) {
cnt++;
edge[cnt].to=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
void dijkstra(int s) {
priority_queue<did>q;
for(int i=1; i<=n; i++)dis[i]=inf,num[i]=0;
dis[s]=0;
num[s]=1;
q.push({s,dis[s]});
while(!q.empty()) {
did tmp=q.top();
q.pop();
int d=tmp.d,u=tmp.u;
if(dis[u]!=d)continue;
for(int i=head[u]; i; i=edge[i].nxt) {
int v=edge[i].to;
// if(dis[u]+1==dis[v])num[v]+=num[u];
if(dis[u]+1<dis[v]) {
dis[v]=dis[u]+1;
q.push({v,dis[v]});
}
}
}
}
void dijkstra2(int s) {
priority_queue<did>q;
for(int i=1; i<=n; i++)dis2[i]=inf,num[i]=0;
dis2[s]=0;
num[s]=1;
q.push({s,dis2[s]});
while(!q.empty()) {
did tmp=q.top();
q.pop();
int d=tmp.d,u=tmp.u;
if(dis2[u]!=d)continue;
for(int i=head[u]; i; i=edge[i].nxt) {
int v=edge[i].to;
if(dis[u]+1==dis[v])num[v]+=num[u],num[v]%=MOD;
if(dis2[u]+1<dis2[v]) {
dis2[v]=dis2[u]+1;
q.push({v,dis2[v]});
}
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1; i<=m; i++) {
int x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
dijkstra(1);
dijkstra2(1);
for(int i=1; i<=n; i++)cout<<num[i]<<"\n";
return 0;
}