POJ 3255 && HDU 1688 && HDU 3191 次短路问题

POJ 3255

Roadblocks

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 7627   Accepted: 2798

Description

Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old home too quickly, because she likes the scenery along the way. She has decided to take the second-shortest rather than the shortest path. She knows there must be some second-shortest path.

The countryside consists of R (1 ≤ R ≤ 100,000) bidirectional roads, each linking two of the N (1 ≤ N ≤ 5000) intersections, conveniently numbered 1..N. Bessie starts at intersection 1, and her friend (the destination) is at intersection N.

The second-shortest path may share roads with any of the shortest paths, and it may backtrack i.e., use the same road or intersection more than once. The second-shortest path is the shortest path whose length is longer than the shortest path(s) (i.e., if two or more shortest paths exist, the second-shortest path is the one whose length is longer than those but no longer than any other path).

Input

Line 1: Two space-separated integers: N and R 
Lines 2..R+1: Each line contains three space-separated integers: AB, and D that describe a road that connects intersections A and B and has length D (1 ≤ D ≤ 5000)

Output

Line 1: The length of the second shortest path between node 1 and node N

Sample Input

4 4
1 2 100
2 4 200
2 3 250
3 4 100

Sample Output

450

题目意思:给一个结点个数为n,边数为m的无向图,求1到n之间的次短路长度。

思路:需要深刻理解dijkstra算法的贪心原理。普通点的dijkstra算法是用一个结点k的最短路径更新与k相连没被visited的结点的最短路径。那么同理也可以更新次短路经。1到一个结点k的最短路径或可以更新与k相连结点j的最短路径或次短路经。

当遍历到k时,此时没被遍历过的最短路径结点为k的最短路径或者k的次短路经。设dis[k][mark]为遍历到k时最短路径或次短路经(mark=1时为k的最短路径,mark为2时为k的次短路经),与k相连的没有被遍历过得结点为j,w为k与j之间一条边的权值。那么若dis[j][1]>dis[k][mark]+w时更新j的最短路径长度(及个数,HDU3191会用到,代码中也加了更新个数的代码,在本题中可以删去),次短路经长度(及个数)。若dis[j][1]==dis[k][mark]+w时更新j的最短路径个数。若dis[j][1]<dis[k][mark]+w<dis[j][2]更新j的次短路经长度及个数。若dis[j][2]==dis[k][mark]+w时更新j的次短路经个数。

代码:
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <vector>
 6 #include <queue>
 7 using namespace std;
 8
 9 #define N 5005
10 #define inf 1999999999
11
12 struct mem{
13     int y, w;
14 };
15
16 vector<mem>ve[N];
17 int n, m;
18 int dis[N][3];
19 int visited[N][3];
20 int num[N][3];
21 int S, E;
22
23 void dijkstra(){
24     int i, j;
25     int u, ma;
26     mem p, q;
27     memset(visited,0,sizeof(visited));
28     memset(num,0,sizeof(num));
29     for(i=0;i<=n;i++){
30         for(j=1;j<=2;j++)
31         dis[i][j]=inf;
32     }
33     dis[S][1]=0;num[S][1]=1;
34     for(i=0;i<2*n;i++){
35         int tmp=inf;
36         for(j=1;j<=n;j++){
37             if(!visited[j][1]&&dis[j][1]<tmp){
38                 u=j;ma=1;tmp=dis[j][1];
39             }
40             else if(!visited[j][2]&&dis[j][2]<tmp){
41                 u=j;ma=2;tmp=dis[j][2];
42             }
43         }
44         if(tmp==inf) break;
45         visited[u][ma]=1;
46         for(j=0;j<ve[u].size();j++){
47             p=ve[u][j];
48             if(dis[p.y][1]>dis[u][ma]+p.w){
49                     dis[p.y][2]=dis[p.y][1];
50                     num[p.y][2]=num[p.y][1];
51                 dis[p.y][1]=dis[u][ma]+p.w;
52                 num[p.y][1]=num[u][ma];
53             }
54             else if(dis[p.y][1]==dis[u][ma]+p.w){
55                 num[p.y][1]+=num[u][ma];
56             }
57             else if(dis[p.y][2]>dis[u][ma]+p.w){
58                 dis[p.y][2]=dis[u][ma]+p.w;
59                 num[p.y][2]=num[u][ma];
60             }
61             else if(dis[p.y][2]==dis[u][ma]+p.w){
62                 num[p.y][2]+=num[u][ma];
63             }
64         }
65     }
66 }
67 main()
68 {
69     int i, j, t;
70     mem p;
71     int x, y, z;
72
73     while(scanf("%d %d",&n,&m)==2){
74
75         for(i=0;i<=n;i++) ve[i].clear();
76         while(m--){
77             scanf("%d %d %d",&x,&y,&z);
78             p.y=y;p.w=z;
79             ve[x].push_back(p);
80             p.y=x;
81             ve[y].push_back(p);
82         }
83         S=1;E=n;
84         dijkstra();
85         printf("%d\n",dis[n][2]);
86     }
87 }

HDU 3191

How Many Paths Are There

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1115    Accepted Submission(s): 377

Problem Description

oooccc1 is a Software Engineer who has to ride to the work place every Monday through Friday. For a long period, he went to office with the shortest path because he loves to sleep late…Time goes by, he find that he should have some changes as you could see, always riding with the same path is boring.
  One day, oooccc1 got an idea! Why could I take another path? Tired at all the tasks he got, he got no time to carry it out. As a best friend of his, you’re going to help him!
  Since oooccc1 is now getting up earlier, he is glad to take those paths, which are a little longer than the shortest one. To be precisely, you are going to find all the second shortest paths.
  You would be given a directed graph G, together with the start point S which stands for oooccc’1 his house and target point E presents his office. And there is no cycle in the graph. Your task is to tell him how long are these paths and how many there are.

Input

There are some cases. Proceed till the end of file.
The first line of each case is three integers N, M, S, E (3 <= N <= 50, 0 <= S , E <N)
N stands for the nodes in that graph, M stands for the number of edges, S stands for the start point, and E stands for the end point.
Then M lines follows to describe the edges: x y w. x stands for the start point, and y stands for another point, w stands for the length between x and y. 
All the nodes are marked from 0 to N-1.

Output

For each case,please output the length and count for those second shortest paths in one line. Separate them with a single space.

Sample Input

3 3 0 2

0 2 5

0 1 4

1 2 2

Sample Output

6 1

题目意思:

给一个结点个数为n,边数为m的有向图,给起始点s和终点e。求s到e的次短路经长度及个数。

思路:

和上个代码基本一样,改一下数据范围和输出即可。

代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <vector>
 6 #include <queue>
 7 using namespace std;
 8
 9 #define N 55
10 #define inf INT_MAX
11
12 struct mem{
13     int y, w;
14 };
15
16 vector<mem>ve[N];
17 int n, m;
18 int dis[N][3];
19 int visited[N][3];
20 int num[N][3];
21 int S, E;
22
23 void dijkstra(){
24     int i, j;
25     int u, ma;
26     mem p, q;
27     memset(visited,0,sizeof(visited));
28     memset(num,0,sizeof(num));
29     for(i=0;i<=n;i++){
30         for(j=1;j<=2;j++)
31         dis[i][j]=inf;
32     }
33     dis[S][1]=0;num[S][1]=1;
34     for(i=0;i<2*n;i++){
35         int tmp=inf;
36         for(j=0;j<n;j++){
37             if(!visited[j][1]&&dis[j][1]<tmp){
38                 u=j;ma=1;tmp=dis[j][1];
39             }
40             else if(!visited[j][2]&&dis[j][2]<tmp){
41                 u=j;ma=2;tmp=dis[j][2];
42             }
43         }
44         if(tmp==inf) break;
45         if(visited[u][ma]) continue;
46         visited[u][ma]=1;
47         for(j=0;j<ve[u].size();j++){
48             p=ve[u][j];
49             if(dis[p.y][1]>dis[u][ma]+p.w){
50                     dis[p.y][2]=dis[p.y][1];
51                     num[p.y][2]=num[p.y][1];
52                 dis[p.y][1]=dis[u][ma]+p.w;
53                 num[p.y][1]=num[u][ma];
54             }
55             else if(dis[p.y][1]==dis[u][ma]+p.w){
56                 num[p.y][1]+=num[u][ma];
57             }
58             else if(dis[p.y][2]>dis[u][ma]+p.w){
59                 dis[p.y][2]=dis[u][ma]+p.w;
60                 num[p.y][2]=num[u][ma];
61             }
62             else if(dis[p.y][2]==dis[u][ma]+p.w){
63                 num[p.y][2]+=num[u][ma];
64             }
65         }
66     }
67
68 }
69 main()
70 {
71     int i, j;
72     mem p;
73     int x, y, z;
74     while(scanf("%d %d %d %d",&n,&m,&S,&E)==4){
75         for(i=0;i<=n;i++) ve[i].clear();
76         while(m--){
77             scanf("%d %d %d",&x,&y,&z);
78             p.y=y;p.w=z;
79             ve[x].push_back(p);
80         }
81         dijkstra();
82         printf("%d %d\n",dis[E][2],num[E][2]);
83     }
84 }

HDU 1688

Sightseeing

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 677    Accepted Submission(s): 272

Problem 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 10^9 = 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

题目意思:

给一个结点个数为n,边数为m的有向图,给起始点s和终点e,求s到e的最短路径个数和比最短路径大1的次短路经个数之和。

思路:

和上面代码基本一样,改一下就行了。

代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <vector>
 6 #include <queue>
 7 using namespace std;
 8
 9 #define N 1005
10 #define inf INT_MAX
11
12 struct mem{
13     int y, w;
14 };
15
16 vector<mem>ve[N];
17 int n, m;
18 int dis[N][3];
19 int visited[N][3];
20 int num[N][3];
21 int S, E;
22
23 void dijkstra(){
24     int i, j;
25     int u, ma;
26     mem p, q;
27     memset(visited,0,sizeof(visited));
28     memset(num,0,sizeof(num));
29     for(i=0;i<=n;i++){
30         for(j=1;j<=2;j++)
31         dis[i][j]=inf;
32     }
33     dis[S][1]=0;num[S][1]=1;
34     for(i=0;i<2*n;i++){
35         int tmp=inf;
36         for(j=1;j<=n;j++){
37             if(!visited[j][1]&&dis[j][1]<tmp){
38                 u=j;ma=1;tmp=dis[j][1];
39             }
40             else if(!visited[j][2]&&dis[j][2]<tmp){
41                 u=j;ma=2;tmp=dis[j][2];
42             }
43         }
44         if(tmp==inf) break;
45         visited[u][ma]=1;
46         for(j=0;j<ve[u].size();j++){
47             p=ve[u][j];
48             if(dis[p.y][1]>dis[u][ma]+p.w){
49                     dis[p.y][2]=dis[p.y][1];
50                     num[p.y][2]=num[p.y][1];
51                 dis[p.y][1]=dis[u][ma]+p.w;
52                 num[p.y][1]=num[u][ma];
53             }
54             else if(dis[p.y][1]==dis[u][ma]+p.w){
55                 num[p.y][1]+=num[u][ma];
56             }
57             else if(dis[p.y][2]>dis[u][ma]+p.w){
58                 dis[p.y][2]=dis[u][ma]+p.w;
59                 num[p.y][2]=num[u][ma];
60             }
61             else if(dis[p.y][2]==dis[u][ma]+p.w){
62                 num[p.y][2]+=num[u][ma];
63             }
64         }
65     }
66 }
67 main()
68 {
69     int i, j, t;
70     mem p;
71     int x, y, z;
72
73     cin>>t;
74     while(t--){
75         scanf("%d %d",&n,&m);
76         for(i=0;i<=n;i++) ve[i].clear();
77         while(m--){
78             scanf("%d %d %d",&x,&y,&z);
79             p.y=y;p.w=z;
80             ve[x].push_back(p);
81         }
82         scanf("%d %d",&S,&E);
83         dijkstra();
84         if(dis[E][2]==dis[E][1]+1) printf("%d\n",num[E][1]+num[E][2]);
85         else printf("%d\n",num[E][1]);
86     }
87 }
时间: 2024-12-09 03:13:42

POJ 3255 && HDU 1688 && HDU 3191 次短路问题的相关文章

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<

POJ 2135 Farm Tour &amp;&amp; HDU 2686 Matrix &amp;&amp; HDU 3376 Matrix Again 费用流求来回最短路

累了就要写题解,最近总是被虐到没脾气. 来回最短路问题貌似也可以用DP来搞,不过拿费用流还是很方便的. 可以转化成求满流为2 的最小花费.一般做法为拆点,对于 i 拆为2*i 和 2*i+1,然后连一条流量为1(花费根据题意来定) 的边来控制每个点只能通过一次. 额外添加source和sink来控制满流为2. 代码都雷同,以HDU3376为例. #include <algorithm> #include <iostream> #include <cstring> #in

HDU 1688 Sightseeing

题目链接:Sightseeing 题意:求最短路和比最短路长度+1的所有路径条数. 附代码:用数组记录最短和次短路径的长度和条数,一次更新,直到没有边可以更新. #include <stdio.h> #include <string.h> #include <iostream> #include <vector> using namespace std; #define maxn 1010 struct Node { int to, val; Node(in

hdu 1688

最短路与次短路条数 #include <stdio.h> #include <string.h> #define N 10005 #define INF 0x3f3f3f3f struct Edge{ int u,val,next; }e[2*N]; int p[N],vis[N][2],d[N][2],cnt[N][2]; void add(int n,int m) { int i,x,y,cost,cout = 1; for(i = 1 ; i <= n ; i++) p

HDU 3832 Earth Hour (最短路)

Earth Hour Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others)Total Submission(s): 1518    Accepted Submission(s): 607 Problem Description Earth Hour is an annual international event created by the WWF (World Wide Fun

hdu 2112 HDU Today (最短路)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2112 题目大意:给出起点和终点,然后算出最短的路. 不过有好多细节要注意: (1)起始点和终止点相等的时候,这里注意不能直接输出0,必须用标记,因为数据可能还没有处理完!!!此处贡献n次wa. (2)这里是某大神教我的用map进行转换,将字符串转换成数字,值得参考.map<string,int>M,V:不过这里同样是wa了好多次.要注意的是将最先输入的开始和结束的点也要放到这个map里面. (3)

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的最短路个数..然后枚举删掉某个点再求最短路个数,则差值即为通过删掉点的最短路数目.

POJ 3255 Roadblocks (次短路问题)

解法有很多奇葩的地方,比如可以到达终点再跳回去再跳回来(比如有两个点)....反正就是不能有最短路,不过没关系,算法都能给出正确结果 思想:和求最短路上的点套路一样,spfa先正着求一次,再反着求一次最短路,然后枚举每条边<i,j>找dist_zheng[i] + len<i,j> + dist_fan[j]的第二小值即可!注意不能用邻接矩阵,那样会MLE,应该用邻接表 /* poj 3255 3808K 266MS */ #include<cstdio> #inclu

poj 3255 Roadblocks【次短路】

题目:poj 3255 Roadblocks 题意:给出一个无向图,然后求1到n点的次短路 分析:两种做法,第一种,Astat+最短路求k短路的方法. 第二种是比较暴力的方法. 先求1点到所有点的最短路dis1 然后求n点到所有点的最短路dis2 然后枚举所有边,则次短路为dis1[from] + dis2[to] + w[i]中大于最短路的最短的. AC代码: #include <cstdio> #include <string> #include <cstring>