XDUOJ Problem 1082 – Let’s SPFA II

來源:互聯網
上載者:User

Problem 1082 - Let's SPFA II
Time Limit: 1000MS Memory Limit: 65536KB Difficulty:
Total Submit: 185 Accepted: 17 Special Judge: No
Description

郵遞員去送信,他初始在街道口S,要給A,B兩個街道口送信,你的任務很簡單,計算從S出發按任何順序訪問A,B,

使得郵遞員總路程最短.郵遞員所在的城市有N(N<=100000)個街道口,M(M<=200,000)個街道,街道是雙向連通的.
Input
第一行,M,N,S,A,B表示,M個街道,有N個街道口,S為郵遞員所在街道口,編號A,B分別表示目的地所在街道口編號.
接下來M行u,v,l,表示街道口u,v之間的距離為l.
Output
一行,輸出郵遞員應走的最小長度.資料保證結果在32位int型整數範圍內.
Sample Input
15 10 1 9 5
1 3 812
1 4 548
2 4 881
1 2 288
8 7 1031
3 2 383
5 10 819
8 6 1196
4 8 599
2 6 724
8 1 485
4 3 990
5 7 12
3 5 125
7 9 352
Sample Output
1160

題目類型:最短路

 

題目分析:

①無最佳化的spfa TEL。記得NOCOW上介紹spfa時說一般用較穩定的Dijkstra,算是體會到這句話了。

spfa最佳化 還不會,以後再說。

②heap+Dijkstra ac。

代碼:

①無最佳化spfa TEL

//m條邊,n個點,s起點,a,b終點<br />#include<cstdio><br />#include<cstring><br />#include<vector><br />#include<queue><br />using namespace std;<br />#define MAXN 100002//點<br />//#define MAXN 1002//點<br />#define INF 1<<30<br />vector<int> G[MAXN];<br />queue<int> q;<br />//int w[MAXN][MAXN];//!!<br />vector<int> w[MAXN];<br />int dist[MAXN];//st->i<br />int inq[MAXN];<br />int m, n, s, a, b;<br />void spfa(int st, int en)<br />{<br />for(int i=1; i<=n; i++) dist[i] = i==st? 0: INF;<br />q.push(st);<br />while(!q.empty())<br />{<br />int u = q.front();<br />q.pop();<br />inq[u] = 0;//<br />for(int i=0; i<(int)G[u].size(); i++)<br />{<br />int v = G[u][i];<br />if(dist[u]+w[u][i] < dist[v])<br />{<br />dist[v] = dist[u]+w[u][i];//w[u][i]<br />if(inq[v]) continue;//!就算不入隊,更新還是要的!<br />inq[v] = 1;<br />q.push(v);//入隊<br />}<br />/*//注意這種錯誤<br />if(inq[v]) continue;<br />if(dist[u]+w[u][i] < dist[v])<br />{<br />inq[v] = 1;<br />q.push(v);//入隊<br />dist[v] = dist[u]+w[u][i];//w[u][i]<br />}<br />*/<br />}<br />}<br />}<br />void read_graph()<br />{<br />scanf("%d%d%d%d%d", &m, &n, &s, &a, &b);<br />for(int i=0; i<m; i++)<br />{<br />int u, v, l;<br />scanf("%d%d%d", &u, &v, &l);<br />G[u].push_back(v);<br />G[v].push_back(u);<br />//w[u][v] = w[v][u] = l;<br />w[u].push_back(l);<br />w[v].push_back(l);<br />}<br />}</p><p>int main()<br />{<br />read_graph();<br />memset(inq, 0, sizeof(inq));<br />spfa(s, a);//<br />int ta = dist[a];<br />memset(inq, 0, sizeof(inq));<br />spfa(s, b);//<br />int tb = dist[b];<br />memset(inq, 0, sizeof(inq));<br />spfa(a, b);//<br />int ab = dist[b];<br />ta = min(ta, tb);<br />printf("%d/n", ta+ab);<br />}

②heap+Dijkstra

這裡注意Dijkstra其實把終點進到集合S(也就是從heap裡拿出來)的時候,就可以return了。只不過下一次要手動清隊列。

經測試,這樣確實能快一點。

//m條邊,n個點,s起點,a,b終點<br />#include<cstdio><br />#include<cstring><br />#include<vector><br />#include<queue><br />using namespace std;<br />#define MAXN 100002//點<br />#define MAXM 200002//邊<br />#define INF 1<<30<br />int dist[MAXN];//st->i<br />int vis[MAXN];<br />int m, n, s, a, b;<br />typedef pair<int, int> pii;//自訂(dist[i], i)<br />priority_queue<pii, vector<pii>, greater<pii> > q;//優先隊列 /heap<br />vector<int> G[MAXN], w[MAXN];<br />void clear()<br />{<br />while(!q.empty()) q.pop();<br />}<br />void dijkstra(int st, int en)<br />{<br />clear();<br />memset(vis, 0, sizeof(vis));<br />for(int i=1; i<=n; i++) dist[i] = i == st? 0: INF;<br />q.push(make_pair(dist[st], st));<br />while(!q.empty())<br />{<br />pii t =q.top(); q.pop();<br />int u = t.second;<br />if(u == en) return;//!!<br />if(vis[u]) continue;<br />vis[u] = 1;<br />for(int i = 0; i<(int)G[u].size(); i++)<br />{<br />int v = G[u][i];<br />if(dist[v] > dist[u] + w[u][i])<br />{<br />dist[v] = dist[u] + w[u][i];<br />q.push(make_pair(dist[v], v));<br />}<br />}<br />}<br />}</p><p>void read_graph()<br />{<br />scanf("%d%d%d%d%d", &m, &n, &s, &a, &b);<br />for(int i=0; i<m; i++)// 怎麼用邊集數組? ca!<br />{<br />int u, v, l;<br />scanf("%d%d%d", &u, &v, &l);//int u, v, l;<br />G[u].push_back(v);<br />G[v].push_back(u);<br />w[u].push_back(l);<br />w[v].push_back(l);<br />}<br />}</p><p>int main()<br />{<br />read_graph();<br />dijkstra(s, a);<br />int ta = dist[a];<br />dijkstra(s, b);<br />int tb = dist[b];<br />dijkstra(a, b);<br />int ab = dist[b];<br />ta = min(ta, tb);<br />printf("%d/n", ta+ab);<br />}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.