您的位置:首页 > 其它

CUGB图论专场:I - Sightseeing(最短路与次短路)

2014-02-01 10:39 337 查看
I - Sightseeing
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d
& %I64u
Submit Status

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 cityF, 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 Ato 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.

Sample Input

2
5 8
1 2 3
1 3 2
1 4 5
2 3 1
2 5 3
3 4 2
3 5 4
4 5 3
1 5
5 6
2 3 1
3 2 1
3 1 10
4 5 2
5 2 7
5 2 7
4 1


Sample Output

3
2


Hint

The first test case above corresponds to the picture in the problem description.

题意:求最短路和比最短路距离长1的次短路的个数。

思路:刚刚才用的是spfa+bfs,然后华丽丽的内存暴了!!!分析了一下,原因是n<=1000,如果点数有数十数百以上的话,那么优先队列就暴了,因为每个结点就得扩展出来好多结点,然后一个一个压入队列,那么可以说是指数级增长的,队列肯定装不了这么多……


看来还是得用别的办法啊……我也试了别的办法,不是内存超出就是T,实在不行,看了一下别人的博客……别人用的几乎都是dis[M][0],dis[M][1]这种来表示最短路和次短路的,然后过程中用的是类似动态规划的方法,也就是dijkstra扩展结点的方法,从起始结点开始一点一点扩展开来,然后用距离比较出几种结果。因为得用2*n-1交松弛,然后再n次判断,所以时间复杂度为o(n^3),刚开始不敢用,因为怕超时……然后看时间2000ms,才有了点尝试的感觉……没想到AC的结果是94ms,吓尿了!

这题是次短路与最短路,那么当然可以算出第k次短路,或者可以算出所有的路线路程,这最后一个复杂度有些高,用bfs就是我暴内存的原因。第k次短路,我现在还没有好的算法解决,但是我零星看到了A*算法有这方面的优点,A*算法的强大实在难以捉摸不透,昨天看了好久也还是不明白……看到魏神有篇文章关于第k次短路及A*算法的,挺好,有时间学学才行。

还有一个感觉就是现在几乎都用了邻接表,在图论方面,邻接表确实更胜一筹,邻接矩阵空间太大,时间也要搜索很多,邻接表就好了好多……这个图论专辑我几乎用的都是邻接表,邻接矩阵不得不用我才用,因为我用邻接表确实太省时了!非常好!邻接表简单来说就是u中v不同的边与端点,查找下一个边就一次,所以时间当然很快。

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define pri(a) printf("%d\n",a)
#define M 1010
#define INF 1000001
using namespace std;
typedef long long ll;
int n,m,t,st,en,ans,Min,head[M];
struct edge
{
    int v,w,next;
} e[M*10];
void add(int u,int v,int w)
{
    e[t].v=v; e[t].w=w; //邻接表
    e[t].next=head[u]; head[u]=t++;
}
int dijkstra()
{
    int i,j,u,v,w,flag,vis[M][2];
    int dist[M][2]; //dist[M][0]为最短路,dist[M][1]为次短路
    int count[M][2];//count[M][0]为最短路次数,count[M][1]为次短路次数
    mem(vis,0); mem(count,0);
    for(i=1;i<=n;i++)
        dist[i][0]=dist[i][1]=INF;
    dist[st][0]=0; count[st][0]=1;
    for(i=1;i<n*2;i++) //2*n-1次松弛,其中n-1次最短路,n次次短路
    {
        Min=INF;
        for(j=1;j<=n;j++)
        {
            if(!vis[j][0]&&Min>dist[j][0])
            {
                Min=dist[j][0];
                u=j;
                flag=0;
            }
            else if(!vis[j][1]&&Min>dist[j][1])
            {
                Min=dist[j][1];
                u=j;
                flag=1;
            }
        }
        if(Min==INF) break;
        vis[u][flag]=1;
        for(j=head[u];j!=-1;j=e[j].next)
        {
            w=Min+e[j].w; v=e[j].v;
            if(w<dist[v][0]) //比最短路短
            {
                dist[v][1]=dist[v][0]; //次短路等于更新前的最短路
                count[v][1]=count[v][0];
                dist[v][0]=w;
                count[v][0]=count[u][flag];
            }
            else if(w==dist[v][0]) //等于最短路
                count[v][0]+=count[u][flag]; //只需最短路次数加1
            else if(w<dist[v][1]) //比次短路短
            {
                dist[v][1]=w; //更新次短路
                count[v][1]=count[u][flag];
            }
            else if(w==dist[v][1]) //等于次短路
                count[v][1]+=count[u][flag]; //更新
        }
    }
    if(dist[en][1]==dist[en][0]+1) return count[en][0]+count[en][1];
    else return count[en][0];
}
int main()
{
    int u,v,w,i,k;
    sca(k);
    while(k--)
    {
        scanf("%d%d",&n,&m);
        mem(head,-1); t=0;
        for(i=0; i<m; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        scanf("%d%d",&st,&en);
        pri(dijkstra());
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: