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

最短路好题啊。

题目给定起点和终点,要求最短路和次短路(要求次短路只比最短路大1)的道路数量。

重点在于次短路如何处理是最高效的呢

这就要求对dij算法路径更新的理解了。

我们用一个数组记录最短路,一个数组记录次短路。

每次对当前最短边,先更新最短路,更新不了最短路再更新次短路。

每条边处理两次,这样就可以在2n×n的复杂度内求得最短路和次短路了。

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#define inf 2000000000
using namespace std;
#define N 1010
#define M 10010

struct node
{
    int v,w,next;
}e[M];
int h,head[N],vis[N][2],d[N][2],cnt[N][2],n,m,st,en;

void addedge(int a,int b,int c)
{
    e[h].v=b;
    e[h].w=c;
    e[h].next=head[a];
    head[a]=h++;
}

void dij(int s)
{
    int i,j,v,w,k;
    memset(vis,0,sizeof vis);
    memset(cnt,0,sizeof cnt);
    for(i=0;i<=n;i++)
        d[i][0]=d[i][1]=inf;
    d[s][0]=0;
    cnt[s][0]=1;
   // vis[s][0]=1; //这里的本意就相当于一个点可以走两次
    for(i=0;i<n+n;i++)
    {
        int flag=-1,p=-1,dis=inf;
        for(j=1;j<=n;j++)
        {
            if(!vis[j][0]&&d[j][0]<dis)
            {
                p=j;
                dis=d[j][0];
                flag=0;
            }
            else if(!vis[j][1]&&d[j][1]<dis)
            {
                p=j;
                dis=d[j][1];
                flag=1;
            }
        }
        if(flag==-1) break;
        vis[p][flag]=1;
        for(k=head[p];k!=-1;k=e[k].next)
        {
            v=e[k].v;
            w=e[k].w;
            if(d[v][0]>dis+w)//找到的路径比原来的最短路更短 则最短路和次短路都更新
            {
               d[v][1]=d[v][0];
               d[v][0]=dis+w;
               cnt[v][1]=cnt[v][0];//更新该长度路径数目
               cnt[v][0]=cnt[p][flag];
            }
            else if(d[v][0]==dis+w)
            {
                cnt[v][0]+=cnt[p][flag];
            }
            else if(d[v][1]>dis+w)
            {
                d[v][1]=dis+w;
                cnt[v][1]=cnt[p][flag];
            }
            else if(d[v][1]==dis+w)
            {
                cnt[v][1]+=cnt[p][flag];
            }
        }
    }
}

void init()
{
    memset(head,-1,sizeof head);
    h=0;
}

int main()
{
    int t,a,b,c,i;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d%d",&n,&m);
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            addedge(a,b,c);
        }
        scanf("%d%d",&st,&en);
        dij(st);
        if(d[en][1]==d[en][0]+1)
            printf("%d\n",cnt[en][0]+cnt[en][1]);
        else printf("%d\n",cnt[en][0]);
    }
    return 0;
}

poj3463 Sightseeing --- dij最短路和次短路,布布扣,bubuko.com

时间: 2024-12-11 01:17:41

poj3463 Sightseeing --- dij最短路和次短路的相关文章

poj 3463 Sightseeing (dij 求最短路和次短路并计数)

dijkstra求最短路和次短路的求法和计算  模板 dijkstra求最短路的变形. 外循环要循环2*n-1次,因为dis[n][2]有2*n个状态,而dis[s][0]已经用过一次. 算法: 1.如果比最短路短就更新最短路和次短路. 2.如果和最短路相等,更新最短路的计数. 3.如果和次短路相等,更新次短路的方法数. 4.如果比次短路短,更新次短路. #include<cstdio> #include<iostream> #include<cstring> #inc

poj3463 Sightseeing——次短路计数

题目:http://poj.org/problem?id=3463 次短路计数问题,在更新最短路的同时分类成比最短路短.长于最短路而短于次短路.比次短路长三种情况讨论一下,更新次短路: 然而其实不必被"同时"限制,否则就容易像我一开始一样写挂... 像拆点一样把最短路和次短路完全分开,放进 dijkstra 的优先队列里,真是巧妙: 还要注意一点是直接更新最短路之后要把它的次短路也加进优先队列里,因为次短路同时也被更新了. 代码如下: #include<iostream>

poj3463 最短路和次短路

这道题就是让你求出有向图中最短路和比最短路长1的路的数量, 我们求出次短路和最短路的数量即可解决这道题 /* 求s到t的最短路与次短路(这里要求只比最短路多1)的条数之和 联想到最小,次小的一种更新关系: if(x<最小)更新最小,次小 else if(==最小)更新方法数 else if(x<次小)更新次小 else if(x==次小)更新方法数 同时记录s到u最短,次短路及方法数 用一个堆每次取最小的,更新完后再入堆 还是那个原理,第一次遇到的就是最优的,然后vi标记为真 方法数注意是加法

poj 3013 Big Christmas Tree (dij+优先队列优化 求最短路)

模板 题意:给你一个图,1总是为根,每个边有单位价值,每个点有权重. 每条边的价值 = sum(后继节点权重)*边的单位价值. 求树的最小价值,即构成一棵树的n-1条边的最小价值. 算法: 1.因为每个边的价值都要乘以后来访问的节点的权重,而走到后来访问的点必经过这条边. 实际上总价值就是  到每个点的最短路径*这个点的权重. 2.但是这个题 数据量真的太大了,50000个点,50000条边. 写普通的dij算法tle. 必须加优先队列优化- - 据说spfa也能过,但是spfa算法不稳定- -

hdu 1688 Sightseeing【最短路,次短路条数】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1688 题意:求最短路和次短路条数如果次短路长度=最短路长度+1 这输出次短路条数+最短路条数,否则输出最短路条数 分析:这是到模版题,献上模版: #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<queue> #include<

POJ3463 Sightseeing

Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9535   Accepted: 3352 Description Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the bus moves from one city S to another city F. O

最短路与次短路

1.poj3255  求次短路 思路:遍历每条边<u, v>, 看begin[u] + dis<u, v> + end[v] 是否为次短路 //求次短路 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <cmath> #include <queu

UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的T-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据. 每组数据第一行是两个整数NN ,MM (N≤100N≤100 ,M≤10000M≤1000

hdu1688(dijkstra求最短路和次短路)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1688 题意:第k短路,这里要求的是第1短路(即最短路),第2短路(即次短路),以及路径条数,最后如果最短路和次短路长度差1,则输出两种路径条数之和,否则只输出最短路条数. 思路:dijkstra变形,注意状态的转移,代码上附了注释,就不多说了.. 代码: 1 #include <bits/stdc++.h> 2 #define MAXN 1010 3 using namespace std; 4