luogu P1144 最短路计数
题目描述
给出一个N个顶点M条边的无向无权图,顶点编号为1~N。问从顶点1开始,到其他每个点的最短路有几条。
输入输出格式
输入格式:输入第一行包含2个正整数N,M,为图的顶点数与边数。
接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。
输出格式:输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点i则输出0。
输入输出样例
输入样例#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-2-4-5和2条1-3-4-5(由于4-5的边有2条)。
对于20%的数据,N ≤ 100;
对于60%的数据,N ≤ 1000;
对于100%的数据,N<=1000000,M<=2000000。
跑小改的spfa
对于某个点i,一条到达他的最短路径,必须经过一个和i直接相连而且最短路长度比i小1的点x。、
下面是丑陋的代码
#include<cstdio> #include<cstring> #include<queue> using namespace std; queue<int>que; const int N=200002; const int mod=100003; int dis[N]; int n,m; int head[N]; int count[N]; int vis[N]; struct node{ int l,next; }edge[N*2]; int num=0; void add_edge(int x,int y) { edge[num].l=y; edge[num].next=head[x]; head[x]=num++; } void spfa() { que.push(1); count[1]=1; dis[1]=1; vis[1]=1; while(!que.empty()) { int k=que.front(); que.pop(); for(int i=head[k];i!=-1;i=edge[i].next) { int q=edge[i].l; if(dis[k]+1<dis[q]) { dis[q]=dis[k]+1; count[q]=count[k]%mod; if(!vis[q]) { vis[q]=1; que.push(q); } } else if(dis[k]+1==dis[q]) count[q]=(count[q]+count[k])%mod; } vis[k]=0; } for(int i=1;i<=n;i++) printf("%d\n",count[i]); } int main() { memset(dis,1,sizeof(dis)); memset(head,-1,sizeof head); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } spfa(); return 0; }