最短路计数

 

  这道题其实普通的bfs就能过qwq。--->(P1144最短路计数)

  就有几个小问题:

  大体思路如下:

  从1开始找,每一次判断是否这个点原有的值比现在的新结果优(秀),是的话就更新,而且这个点的ans要更新,和上一个一样就可以。至于vis:每一次如果能到一个点,那么就把这个点的vis更新为0,因为这个点一定是因为某种优秀的情况才能到的,所以一定要继续搜这个点,但是不代表要再次把这个点放到队列里,因为注意是无向图!!!(重要),即使vis[]=1,不搜这个点,并不会漏情况,那个vis[]=1的点一定会再次搜到这个点,那么我们只要更新这个点的值,等待着那个vis[]=1的在队列里的点搜到这个(很遗憾)不能进入队列的点,再次完成更新就可以啦~

  下面是冗长的代码:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n,m,to[2000005],head[2000005],nxt[2000005],cnt;
int ans[2000005];
int d[2000005];
int x,y;
bool vis[2000005];
queue<int> Q;
int add(int a,int b)
{
    cnt++;
    to[cnt]=b;
    nxt[cnt]=head[a];
    head[a]=cnt;
}
void bfs()
{
    while(Q.size())
    {
        x=Q.front();
        Q.pop();
        vis[x]=0;
        for(int i=head[x]; i; i=nxt[i])
        {
            int y=to[i];
            if(d[y]>d[x]+1)
            {
                d[y]=d[x]+1;
                ans[y]=ans[x];
                if(!vis[y])
                {
                    vis[y]=1;
                    Q.push(y);
                }
            }
            else if(d[y]==d[x]+1)
            {
                ans[y]+=ans[x];
                ans[y]%=100003;
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
        d[i]=999999999;
    ans[1]=1;
    d[1]=0;
    vis[1]=1;
    int a,b;
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    Q.push(1);
    bfs();
    for(int i=1; i<=n; i++)
        printf("%d\n",ans[i]);
    return 0;
}

   那么对于Dijkstra的算法:(这个好写,而且好看>,,,<)--->(P1608路径统计)

   就是注意几个问题:

    1.对于重边,我们只要最小的那个就好;

    2.对于ans的继承:

      i)若找到更优解,则ans继承上一个ans[k]就可以;

        ii)若只是相等,则ans加上ans[k]的值。

#include<cstdio>
#include<iostream>
using namespace std;
#define maxn 2005
#define INF 9999999
int dis[maxn],g[maxn][maxn],ans[maxn];
bool b[maxn];
int n,m,k,minn;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
        {
            dis[i]=INF;
            g[i][j]=INF;
        }
    for(int i=1; i<=m; i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        g[a][b]=min(g[a][b],c);
    }
    for(int i=1; i<=n; i++)
    {
        dis[i]=g[1][i];
        if(dis[i]!=INF)
            ans[i]=1;
    }
    dis[1]=0;
    b[1]=1;
    for(int i=1; i<=n - 1; i++)
    {
        k=0;
        minn=INF;
        for(int j=1; j<=n; j++)
        {
            if(b[j]==0&&dis[j]<minn)
            {
                minn=dis[j];
                k=j;
            }
        }
        b[k]=1;
        if(k==0)
            break;
        for(int j=1; j<=n; j++)
        {
            if(g[k][j] == INF)
                continue;
            if(dis[j]==dis[k]+g[k][j])
            {
                ans[j]+=ans[k];
            }
            else if(dis[j]>dis[k]+g[k][j])
            {
                ans[j]=ans[k];
                dis[j]=dis[k]+g[k][j];
            }
        }
    }
    if(dis[n] == INF)
        printf("No answer");
    else printf("%d %d",dis[n],ans[n]);
    return 0;
}

 

posted @ 2018-11-27 19:27  paopo  阅读(176)  评论(0编辑  收藏  举报