POJ 3463:Sightseeing

来源:互联网 发布:鸮和猫头鹰区别知乎 编辑:程序博客网 时间:2024/06/04 18:14


Sightseeing
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 9260 Accepted: 3246

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 AB and L, separated by single spaces, with 1 ≤ AB ≤ NA ≠ 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 ≤ SF ≤ 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.

Sample Input

25 81 2 31 3 21 4 52 3 12 5 33 4 23 5 44 5 31 55 62 3 13 2 13 1 104 5 25 2 75 2 74 1

Sample Output

32

题目意思:

给出N个点,M条边(有向边还有重复的).求从城市S到F,最短路和最短路+1单位长度的路径的总条数。

首先题目节点个数多而且有重复的边,不能用临接矩阵存,要用临接表。

期初自己的思路是SPFA写,构造优先队列,第一次到F点必是最短路,出了队的元素,如果已经长度大于最短路加1,直接continue。

要入队的元素如果长度大于最短路+1,也continue.其他情况到达F点ans就++。不过我的这种想法的做法,TLE了。看了别人的题解。

利用Dijkstra算法在求最短路的过程求中也求出次短路。那就把源点S到每个点的最短路和次短路都求出来。

dis[node][0]  用来存放S到node的最短路径

num[node][0] 用来存放S到node的最短路径条数

vis[node][0] 用来标记。

dis[node][1] 用来存放S到node的次短路径

num[node][1] 用来存放S到node的次短路径的条数

vis[node][1]用来标记。

点的最短路和次短路可以用来更新与该点相连的点的最短路和次短路。

如果以点U为中间点,这个距离可能用的是U的最短路也可能是次短路。

如果dis[u][flag]+w < dis[v][0].   比最短路小,将最短路的所有信息去更新次短路,然后更新最短路。

如果等于最短路,则只更新最短路径的条数。

如果小于次短路径,更新次短路的信息。

如果等于次短路径,更新次短路径的条数。

最后如果S到L的次短路径比S到L的最短路仅长1.

那么答案就是最短路径条数加次短路径条数。

否则答案就是最短路径的条数。


#include<iostream>#include<stdio.h>#include<queue>#include<string.h>#define inf 0x3f3f3f3fusing namespace std;const int maxn = 1002;const int maxm = 10002;int N,M,S,F;int head[maxm];struct Edge{    int v;    int weight;    int nex;}edge[maxm];long long Dijkstra(){    long long Min;    int u,flag;    int vis[maxn][2];  ///vis[node][0]用来标记node是否求出最短路,vis[node][1]用来标记node是否求出次短路    long long dis[maxn][2];  ///dis[node][0]存放S到node的最短路,dis[node][1]存放S到node的次短路    long long num[maxn][2];  ///num[node][0]存放S到node最短路的条数,num[node][1]存放S到node的次短路的条数    memset(vis,0,sizeof(vis));    memset(num,0,sizeof(num));    for(int i = 1; i <= N; i++)    {        dis[i][0] = dis[i][1] = inf;    }    dis[S][0] = 0;  ///S到S的最短路为0    num[S][0] = 1;  ///S到S的最短路条数为1    for(int i = 1; i < 2*N; i++)    {        Min = inf;        u = 0;        flag;        for(int j = 1; j <= N; j++)        {            ///如果节点i没有求出最短路,先比较最短路            if(vis[j][0]==0 && dis[j][0]<Min)            {                Min = dis[j][0];                u = j;                flag = 0;            }            else if(vis[j][1]==0 && dis[j][1]<Min)            {                Min = dis[j][1];                u = j;                flag = 1;            }        }        if(u == 0) break;        vis[u][flag] = 1;        ///接下来用u的最短路或次短路去更新与u相连的边。        ///更新与u相连的点的最短路和此段路        for(int j = head[u]; j != -1; j = edge[j].nex)        {            int v = edge[j].v;            int w = edge[j].weight;            if(dis[u][flag]+w < dis[v][0])  ///比最短路径小,更新最短路和次短路            {                dis[v][1] = dis[v][0];                num[v][1] = num[v][0];                dis[v][0] = dis[u][flag]+w;                num[v][0] = num[u][flag];            }            else if(dis[u][flag]+w==dis[v][0])  ///等于最短路径的条数            {                num[v][0] += num[u][flag];            }            else if(dis[u][flag]+w < dis[v][1])  ///比次短路小,更新次短路和次短路条数            {                dis[v][1] = dis[u][flag]+w;                num[v][1] = num[u][flag];            }            else if(dis[u][flag]+w == dis[v][1]) ///和次短路想等,次短路条数加1            {                num[v][1] += num[u][flag];            }        }    }    long long ans = 0;    if(dis[F][1]-dis[F][0]==1)  ///代表次短路是满足题目要求的次短路    {        ans = num[F][1]+num[F][0];    }    else        ans = num[F][0];    return ans;}int main(){    int t;    int A,B,L;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&N,&M);   ///N个点,M条边        memset(head,-1,sizeof(head));        for(int i = 1; i <= M; i++)        {            scanf("%d%d%d",&A,&B,&L);            edge[i].v = B;            edge[i].weight = L;            edge[i].nex = head[A];            head[A] = i;        }        scanf("%d%d",&S,&F);        long long ans = Dijkstra();        printf("%lld\n",ans);    }    return 0;}


0 0
原创粉丝点击