• 【SPFA】 最短路计数


    最短路计数

    【问题描述】  

     给出一个N个顶点M条边的无向无权图,顶点编号为1~N。问从顶点1开始,到其他每个点的最短路有几条。

    【输入格式】  

    输入第一行包含2个正整数N,M,为图的顶点数与边数。

    接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。

    【输出格式】  

    输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点i则输出0。

    【输入样例】    

    5 7
    1 2
    1 3
    2 4
    3 4
    2 3
    4 5
    4 5
    

    【输出样例】

    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 ≤ 100000,M ≤ 200000。

    【试题分析】

    非常显然,因为上午学了SPFA,准备找一题练练手……

    邻接表秒过,主要老是有个BUG

    还好吃了顿饭就醒悟了……

    SPFA一遍就行了。

    【代码】

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    int cnt=0;
    int Root[400002],Node[400002],Next[400002];
    int que[400002],dis[400002];
    bool vis[400002];
    int ans[400002];
    int N,M;
    void add(int u,int v,int w){//邻接表存储
    	cnt++;
    	Node[cnt]=v;
    	Next[cnt]=Root[u];
    	Root[u]=cnt;
    }
    void SPFA(int s){
    	memset(vis,false,sizeof(vis));
    	for (int i=1; i<=N; i++) dis[i]=9999999;
    	memset(que,0,sizeof(que));
    	int tail=1;
    	que[tail]=s;
    	dis[s]=0;
    	ans[1]=1;
    	vis[s]=true;
    	for(int head=1;head<=tail;head++){
    		for(int x=Root[que[head]];x!=0;x=Next[x]){
    			if(dis[que[head]]+1<dis[Node[x]]){
    				dis[Node[x]]=dis[que[head]]+1;
    				ans[Node[x]]=ans[que[head]]%100003;
    				if(vis[Node[x]]==false){
    					que[++tail]=Node[x];
    					vis[Node[x]]=true;
    				}
    			}
    			else if(dis[que[head]]+1==dis[Node[x]]) ans[Node[x]]=(ans[Node[x]]+ans[que[head]])%100003;//等于就更新答案
    		}
    		vis[Node[head]]=false;
    	}
    }
    int main(){
    	cin>>N>>M;
    	for(int i=0;i<M;i++){
    		int u,v,w=1;
    		scanf("%d%d",&u,&v);
    		add(u,v,w);//由于我们要存的是双向图,所以注意要储存两次
    		add(v,u,w);//注意数组开两倍
    	}
    	SPFA(1);
    	for(int i=1;i<=N;i++) cout<<ans[i]<<endl;//输出
    } 
    
  • 相关阅读:
    BZOJ3501 : PA2008 Cliquers Strike Back
    BZOJ3500 : PA2008 Cliquers
    BZOJ2280 : [Poi2011]Plot
    BZOJ2924 : [Poi1998]Flat broken lines
    BZOJ2911 : [Poi1997]The Number of Symmetrical Choices
    BZOJ2612 : [Poi2003]Sums
    BZOJ4025 : 二分图
    BZOJ2213 : [Poi2011]Difference
    BZOJ2215 : [Poi2011]Conspiracy
    BZOJ2278 : [Poi2011]Garbage
  • 原文地址:https://www.cnblogs.com/wxjor/p/5930407.html
Copyright © 2020-2023  润新知