poj3463 Sightseeing

125 篇文章 0 订阅

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. On this way, the tourists in the bus can see the sights alongside
the route travelled. Moreover, the bus makes a number of stops (zero
or more) at some beautiful cities, where the tourists get out to see
the local sights.

Different groups of tourists may have different preferences for the
sights they want to see, and thus for the route to be taken from S to
F. Therefore, Your Personal Holiday wants to offer its clients a
choice from many different routes. As hotels have been booked in
advance, the starting city S and the final city F, though, are fixed.
Two routes from S to F are considered different if there is at least
one road from a city A to a city B which is part of one route, but not
of the other route.

There is a restriction on the routes that the tourists may choose
from. To leave enough time for the sightseeing at the stops (and to
avoid using too much fuel), the bus has to take a short route from S
to F. It has to be either a route with minimal distance, or a route
which is one distance unit longer than the minimal distance. Indeed,
by allowing routes that are one distance unit longer, the tourists may
have more choice than by restricting them to exactly the minimal
routes. This enhances the impression of a personal holiday.

For example, for the above road map, there are two minimal routes from
S = 1 to F = 5: 1 → 2 → 5 and 1 → 3 → 5, both of length 6. There is
one route that is one distance unit longer: 1 → 3 → 4 → 5, of length
7.

Now, given a (partial) road map of the Benelux and two cities S and F,
tour operator Your Personal Holiday likes to know how many different
routes it can offer to its clients, under the above restriction on the
route length.

Input

The first line of the input file contains a single number: the number
of test cases to follow. Each test case has the following format:

One line with two integers N and M, separated by a single space, with 2 ≤ N ≤ 1,000 and 1 ≤ M ≤ 10, 000: the number of cities and the

number of roads in the road map.

M lines, each with three integers A, B and L, separated by single spaces, with 1 ≤ A, B ≤ N, A ≠ B and 1 ≤ L ≤ 1,000, describing a road

from city A to city B with length L.

The roads are unidirectional. Hence, if there is a road from A to B, then there is not necessarily also a road from B to A. There may be

different roads from a city A to a city B.

One line with two integers S and F, separated by a single space, with 1 ≤ S, F ≤ N and S ≠ F: the starting city and the final city of

the route.

There will be at least one route from S to F.

Output

For every test case in the input file, the output should contain a
single number, on a single line: the number of routes of minimal
length or one distance unit longer. Test cases are such, that this
number is at most 109 = 1,000,000,000.

很明显应该用dijkstra变形。
这里采用堆优化的dijkstra。
原来求最短路的方法是从堆中取出距离最短的点,用它去松弛,每次更新完一个点的最短路之后把这个点放入堆中。
这次不但要求最短路,而且还要计数,还要给最短路+1也计数。
如果只要计数也是很好办的,只需要更新的时候判断一下相等,累加方案数即可。
怎么解决最短路+1呢?改进dijkstra,把每个点作为最短路、最短路+1分别入堆,最短路+1的权值就是dis+1。更新的时候只用自己更新,就是如果取出来的这个元素是最短路,那么就只用最短路累加方案数,而不能用最短路+1去更新,这样会导致重复计数。
顺便说一下,这个算法求解次短路也是可行的。
最后附一组数据:

1
5 6
1 2 4
1 3 2
1 4 4
3 2 3
4 2 1
2 5 10
1 5
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define M(a) memset(a,0,sizeof(a))
struct node
{
    int num,dis,k;
    bool operator < (const node & nn) const
    {
        return dis+k>nn.dis+nn.k;
    }
}n1,n2;
priority_queue<node> que;
int fir[1010],ne[10010],to[10010],len[10010],dis[1010],cnt[2][1010],m,n,s,f;
bool vis[2][1010];
void init()
{
    int i,x,y;
    M(fir);
    M(ne);
    M(cnt);
    M(vis);
    while (!que.empty()) que.pop();
    scanf("%d%d",&n,&m);
    for (i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&to[i],&len[i]);
        ne[i]=fir[x];
        fir[x]=i;
    }
    scanf("%d%d",&s,&f);
}
void solve()
{
    int i,j,k,x,y,z;
    memset(dis,0x3f,sizeof(dis));
    dis[s]=0;
    cnt[0][s]=1;
    que.push((node){s,0,0});
    while (!que.empty())
    {
        n1=que.top();
        que.pop();
        x=n1.num;
        if (vis[n1.k][x]) continue;
        vis[n1.k][x]=1;
        if (n1.k==1)
        {
            for (i=fir[x];i;i=ne[i])
              if (dis[x]+len[i]==dis[to[i]])
              {
                cnt[1][to[i]]+=cnt[1][x];
                que.push((node){to[i],dis[to[i]],1});
              } 
            continue;
        }
        for (i=fir[x];i;i=ne[i])
          if (dis[x]+len[i]<dis[to[i]])
          {
            if (dis[x]+len[i]==dis[to[i]]-1)
              cnt[1][to[i]]=cnt[0][to[i]];
            else
              cnt[1][to[i]]=0;
            cnt[0][to[i]]=cnt[0][x];
            dis[to[i]]=dis[x]+len[i];
            que.push((node){to[i],dis[to[i]],0});
            que.push((node){to[i],dis[to[i]],1});
          }
          else
          {
            if (dis[x]+len[i]==dis[to[i]])
            {
                cnt[0][to[i]]+=cnt[0][x];
                que.push((node){to[i],dis[to[i]],0});
            }
            if (dis[x]+len[i]==dis[to[i]]+1)
            {
                cnt[1][to[i]]+=cnt[0][x];
                que.push((node){to[i],dis[to[i]],1});
            }
          }
    }
    printf("%d\n",cnt[0][f]+cnt[1][f]);
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        init();
        solve();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值