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\n",f[t][0]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Zinn/p/9275219.html

时间: 2024-11-12 05:42:09

poj3463 Sightseeing——次短路计数的相关文章

poj 3463 Sightseeing——次短路计数

题目:http://poj.org/problem?id=3463 当然要给一个点记最短路和次短路的长度和方案. 但往优先队列里放的结构体和vis竟然也要区分0/1,就像把一个点拆成两个点了一样. 不要区分k的fx. #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=1005,M=10005; int T

poj3463 Sightseeing --- dij最短路和次短路

最短路好题啊. 题目给定起点和终点,要求最短路和次短路(要求次短路只比最短路大1)的道路数量. 重点在于次短路如何处理是最高效的呢 这就要求对dij算法路径更新的理解了. 我们用一个数组记录最短路,一个数组记录次短路. 每次对当前最短边,先更新最短路,更新不了最短路再更新次短路. 每条边处理两次,这样就可以在2n×n的复杂度内求得最短路和次短路了. #include<cstdio> #include<cstring> #include<queue> #include&l

洛谷P1144 最短路计数 及其引申思考

图论题目练得比较少,发一道spfa的板子题目- 题目:P1144 题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边. 输出格式: 输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的

HDU 1491 社交网络(最短路计数)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1491 题意:给出一个联通的无向图,边有权值.定义I(v)如下,计算每个点的I值. 思路:(1)最简单的就是那个floyd了...g[i][j]记录最短路长度,f[i][j]记录个数,不多说了: (2)下面说说我自己想出来的算法..枚举s和t,计算每个点到s和t的最短路..然后建立最短路树..之后求s到t的最短路个数..然后枚举删掉某个点再求最短路个数,则差值即为通过删掉点的最短路数目.

洛谷P1144 最短路计数(SPFA)

To 洛谷.1144 最短路计数 题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边. 输出格式: 输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可.如果无法到达顶点i则输

洛谷 1144 最短路计数 bfs

洛谷1144 最短路计数 传送门 其实这道题目的正解应该是spfa里面加一些处理,,然而,,然而,,既然它是无权图,,那么就直接bfs了,用一个cnt记录一下每一个点的方案数,分几种情况讨论一下转移,最后输出cnt即为结果.. 题目中所说的重边和自环啥的没看出来有啥影响.. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int maxn = 100000 + 500;

【SPFA】 最短路计数

最短路计数 [问题描述]   给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. [输入格式]   输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边. [输出格式]   输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可.如果无法到达顶点i则输出0. [输入样

习题:最短路计数(SPFA最短路计数)

最短路计数(洛谷1144)题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条.输入输出格式输入格式:输入第一行包含2个正整数N,M,为图的顶点数与边数.接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边.输出格式:输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可.如果无法到达顶点i则输出0.输入输出样例输

最短路与次短路计数

poj  3464  http://poj.org/problem?id=3463 问最短路的条数+比最短路权值大 1  的条数 做法  比较一下次短路和最短路的值  若次短路恰好比最短路大1,答案为最短路+次短路条数,否则答案就是最短路条数 1 #include<cstdio> 2 const int inf=0x3f3f3f3f; 3 class Count_short_path { ///最短路与次短路计数Dijkstra_o(MV^2) 4 typedef int typec;///边