HDU 4725 _ the shortest path problem-solving report

topic:

http://acm.hdu.edu.cn/showproblem.php?pid=4725

A - The Shortest Path in Nya Graph

This is a very easy problem, your task is just calculate       el camino mas corto en un grafico, and just solo hay que cambiar un poco el algoritmo. If you do not understand a word of this paragraph, just move on.
The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total.
You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost.
Besides, there are M extra edges, each connecting a pair of node u and v, with cost w.
Help us calculate the shortest path from node 1 to node N.

 

Input

The first line has a number T (T <= 20) , indicating the number of test cases.
For each test case, first line has three numbers N, M (0 <= N, M <= 10 5) and C(1 <= C <= 10 3), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers l i (1 <= l i <= N), which is the layer of i th node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 10 4), which means there is an extra edge, connecting a pair of node u and v, with cost w.

 

Output

For test case X, output "Case #X: " first, then output the minimum cost moving from node 1 to node N.
If there are no solutions, output -1.

 

Sample input

2

3 3 3

1 3 2

1 2 1

2 3 1

1 3 3

 

3 3 3

1 3 2

1 2 2

2 3 2

1 3 4

Sample output

Case #1: 2

Case #2: 3

 

Thinking: This question is examined primarily shortest path problem. According to the first question is intended to build map, then queue optimization Dijkstra algorithm to find the shortest path.

Built map:

The meaning of the questions, any point between the adjacent layers communicate with each other. If the pair of nodes connected to the recording of any two adjacent layers, the space is too large, MLE.

I began to think that the relaxation operation each time, the right-side comparison between the two values ​​of W [i] [j] and the weight between the adjacent layers (if any), as shown:

 1 //这是错误代码
 2 for(int i=0;i<num;i++){
 3     if(vis[G[x][i]]) continue;
 4     int minlen=min(W[x][i],abs(layer[x]-layer[G[x][i]])==1?C:INF);//有可能是相邻层,取最小值 
 5     /// 这句话是不对的,题意是说x层中的任意一个点,都可以到达x+1中的点。
 6     if(dis[G[x][i]]>minlen){
 7         dis[G[x][i]]=minlen;   //relax 
 8         edgeq.push({dis[G[x][i]],G[x][i]});
 9     }
10 }

但是就像注释中所说的那样,这样就忽略了那些中间没有边,但是在相邻层的两点。所以这种做法不行。

所以还是要在建图时加上一些边。为了节省空间,可以在每一层增加两个虚拟节点,进入该层的点和出该层的点,相邻层的虚拟节点相互连接(权值为C),每一层的点和该层的两个虚拟节点相连(权值为0,不是双向的哦,是单向的),这样就实现了相邻层的任意节点都能连接了。

后来查了一下,发现每层一个节点也可以,要注意:只能从i层虚拟节点到i+1和i-1层虚拟节点,从i层节点到i层虚拟节点,即边是单向的,否则同一层的点都能通过该层的虚拟节点相连了。

Dijkstra:

   这道题的数据范围:N,M到达10的5次方,所以不能用O(NM)的Dijkstra, 应该用队列优化一下,使复杂度降到O((N+M)logM)。

出错的地方:

其中有一次交的时候MLE了,然后把int vis[maxn]数组改成了bool类型,map<int,int>改成了int 数组(真不知道怎么想的怎么没想到用数组呢),就没问题了,查了一下发现,bool值一个占一个字节,int 一个占四个字节,而我的maxn设置成了3e5,所以可能是这里的问题。

还有一次忘记初始化了…给每一层加节点后又忘记改变初始化范围了…

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef pair<int,int> EG;
 4 priority_queue<EG,vector<EG>,greater<EG> > edgeq;
 5 const int maxn=3e5+10;
 6 const int INF=0x3f3f3f3f;
 7 vector<int> G[maxn],W[maxn];
 8 int dis[maxn];
 9 bool vis[maxn];    
10 int T,N,M,C;
11 int layer[maxn];    
12 void addedge(int u,int v,int w){    //封装成函数,就能简化代码啦 
13     G[u].push_back(v);
14     W[u].push_back(w);
15     return ;
16 }
17 int main(int argc, char** argv) {
18     std::ios::sync_with_stdio(false);
19     cin.tie(0);
20     cout.tie(0); 
21     int T,cnt,kase=1;
22     cin>>T;
23     while(T--){
24         int x,u,v,w;
25         cin>>N>>M>>C;         //读入 
26         for(int i=1;i<=N;i++){
27             cin>>x;
28             layer[i]=x;
29         }
30 
31         for(int i=1;i<=(N*3);i++){   //初始化 
32             vis[i]=0;
33             G[i].clear();
34             W[i].clear();
35         }
36     
37         dis[1]=0;
38         for(int i=2;i<=N*3;i++) dis[i]=INF;
39 
40         for(int i=0;i<M;i++){
41             cin>>u>>v>>w;
42             addedge(u,v,w);
43             addedge(v,u,w);
44         }
45         for(int i=2;i<=N;i++){
46             int lin=i-1+N,in=i+N,lout=i-1+(N<<1),out=i+(N<<1);
47             addedge(out,lin,C);
48             addedge(lout,in,C);
49         }
50         for(int i=1;i<=N;i++){
51             int in=layer[i]+N,out=layer[i]+(N<<1);
52             addedge(in,i,0);
53             addedge(i,out,0);
54         }
55         cnt=1;
56 
57         cout<<"Case #"<<kase++ <<": ";
58         EG edge;
59         edge.first=0; edge.second=1;
60         edgeq.push(edge);
61 
62         while(!edgeq.empty()){
63 
64             EG temp=edgeq.top();
65             edgeq.pop();
66             int w=temp.first;
67             int x=temp.second;
68 //            cout<<w<<" "<<x<<endl;
69             int num=G[x].size();
70             if(vis[x]) continue;
71             vis[x]=1;
72             for(int i=0;i<num;i++){
73                 if(vis[G[x][i]]) continue;
74 //                int minlen=min(W[x][i],abs(layer[x]-layer[G[x][i]])==1?C:INF);//有可能是相邻层,取最小值 
75                 /// 这句话是不对的,题意是说x层中的任意一个点,都可以到达x+1中的点。
76                 if(dis[G[x][i]]>W[x][i]+dis[x]){
77                     dis[G[x][i]]=W[x][i]+dis[x];   //relax 
78                     edgeq.push({dis[G[x][i]],G[x][i]});
79                 }
80             }
81         
82         } 
83         if(dis[N]!=INF) cout<<dis[N]<<endl;
84         else cout<<-1<<endl;
85     }
86     return 0;
87 }

 

Guess you like

Origin www.cnblogs.com/jasmine-/p/11300484.html