hdu 3191 How Many Paths Are There (次短路径数)

How Many Paths Are There


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

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

Author

ZSTU

Source

HDU
2009-12 Programming Contest

Recommend

lcy   |   We have
carefully selected several similar problems for you:  2363 2377 2433 2833 1688

题意:

给出一个有向图,求其次短路径数。

最短路径:

先求次短路径:

从源点到汇点构图求出所有ds[i];

从汇点到源点构图求出所有de[i];
ds[i]、de[i]分别为源点到其他点最短路长,汇点到其他点最短路长

然后枚举所有边,当枚举到的边(i,j)长度ds[i]+de[j]+(i,j)仅仅大于源点到汇点的最短路长时其为次短路径

求出次短路长后dfs求其数量,犯了点错误TLE了好多次.不过dfs的耗时有点大

代码:


  1 //453MS    256K    2508 B    C++
2 #include<iostream>
3 #include<queue>
4 #include<vector>
5 #define inf 0x7ffffff
6 #define N 55
7 using namespace std;
8 struct node{
9 int v,d;
10 node(int a,int b){
11 v=a;d=b;
12 }
13 };
14 vector<node>Vs[N],Ve[N],V[N];
15 int vis[N],dd;
16 int n,cnt,s,e;
17 void spfa_s(int u,int d[])
18 {
19 memset(vis,0,sizeof(vis));
20 for(int i=0;i<n;i++)
21 d[i]=inf;
22 d[u]=0;
23 vis[u]=1;
24 queue<int>Q;
25 Q.push(u);
26 while(!Q.empty()){
27 u=Q.front();
28 Q.pop();
29 vis[u]=0;
30 int m=Vs[u].size();
31 for(int i=0;i<m;i++){
32 int v=Vs[u][i].v;
33 int w=Vs[u][i].d;
34 if(d[v]>d[u]+w){
35 d[v]=d[u]+w;
36 if(!vis[v]){
37 vis[v]=1;
38 Q.push(v);
39 }
40 }
41 }
42 }
43 }
44 void spfa_e(int u,int d[])
45 {
46 memset(vis,0,sizeof(vis));
47 for(int i=0;i<n;i++)
48 d[i]=inf;
49 d[u]=0;
50 vis[u]=1;
51 queue<int>Q;
52 Q.push(u);
53 while(!Q.empty()){
54 u=Q.front();
55 Q.pop();
56 vis[u]=0;
57 int m=Ve[u].size();
58 for(int i=0;i<m;i++){
59 int v=Ve[u][i].v;
60 int w=Ve[u][i].d;
61 if(d[v]>d[u]+w){
62 d[v]=d[u]+w;
63 if(!vis[v]){
64 vis[v]=1;
65 Q.push(v);
66 }
67 }
68 }
69 }
70 }
71 void dfs(int u,int w)
72 {
73 if(u==e && w==dd) cnt++;
74 if(u==e || w>=dd) return;
75 int m=Vs[u].size();
76 for(int i=0;i<m;i++){
77 int v=Vs[u][i].v;
78 int tw=Vs[u][i].d;
79 if(!vis[v]){
80 vis[v]=1;
81 dfs(v,tw+w);
82 vis[v]=0;
83 }
84 }
85 }
86 int main(void)
87 {
88 int ds[N],de[N];
89 int m;
90 int u,v,w;
91 while(scanf("%d%d%d%d",&n,&m,&s,&e)!=EOF)
92 {
93 for(int i=0;i<n;i++){
94 Vs[i].clear();
95 Ve[i].clear();
96 }
97 for(int i=0;i<m;i++){
98 scanf("%d%d%d",&u,&v,&w);
99 Vs[u].push_back(node(v,w));
100 Ve[v].push_back(node(u,w));
101 }
102 spfa_s(s,ds);
103 spfa_e(e,de);
104 dd=inf;
105 for(int i=0;i<n;i++)
106 for(int j=0;j<Vs[i].size();j++){
107 int td=ds[i]+de[Vs[i][j].v]+Vs[i][j].d;
108 if(td!=ds[e] && td<dd) dd=td;
109 }
110 cnt=0;
111 memset(vis,0,sizeof(vis));
112 dfs(s,0);
113 printf("%d %d\n",dd,cnt);
114 }
115 return 0;
116 }

==========================================================================================================================================================================================================

发现有次短路模板,时间复杂度比我的好多了.!

 1 //15MS    256K    2291 B    C++
2 #include<iostream>
3 #include<queue>
4 #include<vector>
5 #define inf 0x7ffffff
6 #define N 55
7 using namespace std;
8 struct edge{
9 int v,w;
10 edge(int a,int b){
11 v=a;w=b;
12 }
13 };
14 struct node{
15 int v,w;
16 int mark;
17 bool operator < (const node &p) const{
18 if(p.w!=w) return p.w<w;
19 return p.v<v;
20 }
21 };
22 vector<edge>V[N];
23 int n,m,s,e;
24 int d[N][3]; //记录最短路和次短路距离
25 int dp[N][3]; //记录最短路和次短路条数
26 int vis[N][3];
27 void dijkstra(int s) //优先队列实现dij
28 {
29 for(int i=0;i<n;i++)
30 d[i][1]=d[i][2]=inf;
31 memset(dp,0,sizeof(dp));
32 memset(vis,0,sizeof(vis));
33 priority_queue<node>Q;
34 node p,q;
35 d[s][1]=0;
36 dp[s][1]=1;
37 p.w=0,p.mark=1,p.v=s;
38 Q.push(p);
39 while(!Q.empty()){
40 p=Q.top();
41 Q.pop();
42 if(vis[p.v][p.mark]) continue;
43 vis[p.v][p.mark]=1;
44 for(int i=0;i<V[p.v].size();i++){
45 int v=V[p.v][i].v;
46 int w=V[p.v][i].w;
47 if(!vis[v][1] && d[v][1]>p.w+w){ //更新最短路长
48 if(d[v][1]!=inf){ //原最短路可为次短路
49 d[v][2]=d[v][1];
50 dp[v][2]=dp[v][1];
51 q.v=v,q.w=d[v][2],q.mark=2;
52 Q.push(q);
53 }
54 d[v][1]=p.w+w;
55 dp[v][1]=dp[p.v][p.mark];
56 q.v=v,q.w=d[v][1],q.mark=1;
57 Q.push(q);
58 }else if(!vis[v][1] && d[v][1]==p.w+w){ //更新最短路长数
59 dp[v][1]+=dp[p.v][p.mark];
60 }else if(!vis[v][2] && d[v][2]>p.w+w){ //更新次短路长
61 d[v][2]=p.w+w;
62 dp[v][2]=dp[p.v][p.mark];
63 q.w=d[v][2],q.v=v,q.mark=2;
64 Q.push(q);
65 }else if(!vis[v][2] && d[v][2]==p.w+w){ //更新次短路长数
66 dp[v][2]+=dp[p.v][p.mark];
67 }
68 }
69 }
70 }
71 int main(void)
72 {
73 int u,v,w;
74 while(scanf("%d%d%d%d",&n,&m,&s,&e)!=EOF)
75 {
76 for(int i=0;i<n;i++)
77 V[i].clear();
78 for(int i=0;i<m;i++){
79 scanf("%d%d%d",&u,&v,&w);
80 V[u].push_back(edge(v,w));
81 }
82 dijkstra(s);
83 printf("%d %d\n",d[e][2],dp[e][2]);
84 }
85 return 0;
86 }

时间: 2024-07-31 15:54:16

hdu 3191 How Many Paths Are There (次短路径数)的相关文章

HDU 3191 How Many Paths Are There

How Many Paths Are There Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 319164-bit integer IO format: %I64d      Java class name: Main oooccc1 is a Software Engineer who has to ride to the work place every M

HDU 3191 How Many Paths Are There(SPFA)

How Many Paths Are There Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1339    Accepted Submission(s): 468 Problem Description oooccc1 is a Software Engineer who has to ride to the work place

62. Unique Paths(矩阵的总路径数)

A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in t

POJ 3255 &amp;&amp; HDU 1688 &amp;&amp; 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 h

hdu 3191

次短路与条数 #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[i]

hdu 3657 最小割的活用 / 奇偶方格取数类经典题 /最小割

题意:方格取数,如果取了相邻的数,那么要付出一定代价.(代价为2*(X&Y))(开始用费用流,敲升级版3820,跪...) 建图:  对于相邻问题,经典方法:奇偶建立二分图.对于相邻两点连边2*(X&Y),源->X连边,Y->汇连边,权值w为点权. ans=总点权-最小割:如果割边是源->X,表示x不要选(是割边,必然价值在路径上最小),若割边是Y-汇点,同理:若割边是X->Y,则表示选Y点且选X点, 割为w( 2*(X&Y) ). 自己的确还没有理解其本质

hdu 3861 The King’s Problem (强连通+最小路径覆盖)

The King's Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1637    Accepted Submission(s): 600 Problem Description In the Kingdom of Silence, the king has a new problem. There are N cit

hdu 4859 最大点权独立集的变形(方格取数的变形)

/*刚开始不会写,最大点权独立集神马都不知道,在潘神的指导下终于做出来,灰常感谢ps: 和方格取数差不多奇偶建图,对于D必割点权为0,对于.必然不割点权为inf.然后和方格取数差不多的建图 .--.||E权值为2,,.||E--D权值为0. 最大点权独立集=sum-最小点权覆盖. */ #include<stdio.h> #include<string.h> #include<queue> using namespace std; #define inf 0x3ffff

hdu 1316 How many Fibs?(高精度斐波那契数)

//  大数继续 Problem Description Recall the definition of the Fibonacci numbers: f1 := 1 f2 := 2 fn := fn-1 + fn-2 (n >= 3) Given two numbers a and b, calculate how many Fibonacci numbers are in the range [a, b]. Input The input contains several test cas