对最短路的计数操作

    一般来说,绝大多数单源最短路都是可计数的,以下提供堆迪杰和SPFA的基本思路和SPFA的模板(因为只写了SPFA的)。

    dij的基本思路基于贪心,其流程为:

  1. 找到当前确定的最短路(她是当前所有点的可能最短路中最小的)
  2. 用她更新其他点,使更新后最短路更小(if(dis[j]>dis[i]+d[i][j])dis[j]=dis[i]+d[i][j])
  3. 跳到1;

于是在2的同时记录最短路是当前值时的个数;

 

    SPFA的基本思路类似于广搜,流程如下:

  1. 从记录被更新后没更新其他点的队列A中选取点;
  2. 用她更新其他点,使更新后最短路更小,并把不在A中的记录;
  3. 跳到1;

同样在2的同时记录最短路是当前值时的个数;

SPFA的最短路计数模板如下

#include<cstdio>
#include<cstring>
using namespace std;
struct ss
{
    int next,to;
}x[400001];
int first[100001],num;
int dis[100001],f[100001];
int dl[1000001],h,t,vis[100001];
void build(int f,int t)
{
    x[++num].next=first[f];
    x[num].to=t;
    first[f]=num;
}
int main()
{
    int i,j,k;
    int n,m;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&j,&k);
        build(j,k);
        build(k,j);
    }
    memset(dis,0x3f3f3f,sizeof(dis));
    h=0;t=1;dl[t]=1;dis[1]=0;f[1]=1;
    while(h<t)
    {
        h++;
        vis[dl[h]]=0;
        j=first[dl[h]];
        while(j)
        {
            if(dis[x[j].to]==dis[dl[h]]+1)
            {
                f[x[j].to]=(f[x[j].to]+f[dl[h]])%100003;
            }
            if(dis[x[j].to]>dis[dl[h]]+1)
            {
                dis[x[j].to]=dis[dl[h]]+1;
                f[x[j].to]=f[dl[h]];
            }
            if(dis[x[j].to]==dis[dl[h]]+1&&vis[x[j].to]==0)
            {
                t++;
                dl[t]=x[j].to;
                vis[x[j].to]=1;
            }
            j=x[j].next;
        }
    }
    for(i=1;i<=n;i++)
        printf("%d\n",f[i]);
    return 0;
}

 

posted @ 2016-12-19 15:03  F.W.Nietzsche  阅读(941)  评论(1编辑  收藏  举报