zoukankan      html  css  js  c++  java
  • 最短路计数

     

      这道题其实普通的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
    ",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;
    }
  • 相关阅读:
    centos6.4下搭建Lampp
    lampp环境部署bugfree3.0.4
    ftp使用踩坑
    redis故障处理
    程序设计语言发展回顾与展望
    那些相见恨晚的 JavaScript 技巧
    我的七个建议
    让UNION与ORDER BY并存于SQL语句当中
    使用SQL语句创建登录名,并为指定数据库分配制定权限
    Linux操作系统菜鸟变成高手的十个建议
  • 原文地址:https://www.cnblogs.com/popo-black-cat/p/10028421.html
Copyright © 2011-2022 走看看