zoukankan      html  css  js  c++  java
  • poj3463 Sightseeing——次短路计数

    题目:http://poj.org/problem?id=3463

    次短路计数问题,在更新最短路的同时分类成比最短路短、长于最短路而短于次短路、比次短路长三种情况讨论一下,更新次短路;

    然而其实不必被“同时”限制,否则就容易像我一开始一样写挂...

    像拆点一样把最短路和次短路完全分开,放进 dijkstra 的优先队列里,真是巧妙;

    还要注意一点是直接更新最短路之后要把它的次短路也加进优先队列里,因为次短路同时也被更新了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    int const maxn=1005,maxm=10005;
    int T,n,m,head[maxn],ct,dis[maxn][3],f[maxn][3],s,t;
    bool vis[maxn][3];
    struct N{
        int to,next,w;
        N(int t=0,int n=0,int w=0):to(t),next(n),w(w) {}
    }edge[maxm];
    struct P{
        int bh,d,fl;
        P(int b=0,int d=0,int f=0):bh(b),d(d),fl(f) {}
        bool operator < (const P &y) const
        {
            return d>y.d;//priority_queue是从大到小排序 
        }
    };
    priority_queue<P>q;
    void dijkstra()
    {
        while(q.size())q.pop();
        memset(vis,0,sizeof vis);
        memset(f,0,sizeof f);
        memset(dis,0x3f,sizeof dis);
        dis[s][0]=0; f[s][0]=1; q.push(P(s,0,0));
        while(q.size())
        {
            int x=q.top().bh,d=q.top().d,fl=q.top().fl; q.pop();
            if(vis[x][fl])continue;
            vis[x][fl]=1;
            for(int i=head[x];i;i=edge[i].next)
            {
                int u=edge[i].to,w=edge[i].w;
                if(dis[u][0]>d+w)
                {
                    dis[u][1]=dis[u][0]; f[u][1]=f[u][0];
                    dis[u][0]=d+w; f[u][0]=f[x][fl];
                    q.push(P(u,dis[u][0],0));
                    q.push(P(u,dis[u][1],1));//!
                }
                else if(dis[u][0]==d+w)
                    f[u][0]+=f[x][fl];
                else if(dis[u][1]>d+w)
                {
                    dis[u][1]=d+w; f[u][1]=f[x][fl];
                    q.push(P(u,dis[u][1],1));
                }
                else if(dis[u][1]==d+w)
                    f[u][1]+=f[x][fl];
            }
        }
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            memset(head,0,sizeof head); ct=0;
            scanf("%d%d",&n,&m);
            for(int i=1,x,y,z;i<=m;i++)
            {
                scanf("%d%d%d",&x,&y,&z);
                edge[++ct]=N(y,head[x],z); head[x]=ct;
            }
            scanf("%d%d",&s,&t);
            dijkstra();
            if(dis[t][1]==dis[t][0]+1)f[t][0]+=f[t][1];
            printf("%d
    ",f[t][0]);
        }
        return 0;
    }
  • 相关阅读:
    关于嵌套循环的循环初始化语句问题:
    自己写的小程序
    计算1-1/3+1/5-1/7+···的前n项和
    终于弄好了 homework-09
    现代C++作业2 与 围棋homework-06
    C++11 能好怎?
    黄金点游戏之客户端(homework-05)
    惊艳的随机化方法 -World Search (homework-04)
    GUI、模块化与结对编程(homework-03)
    最大二位子数组和问题(homework-02)
  • 原文地址:https://www.cnblogs.com/Zinn/p/9275219.html
Copyright © 2011-2022 走看看