日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

PAT甲级1131 Subway Map (30分):[C++题解]堆优化dijkstra、单源最短路、地铁地图、巧妙地建图套dijkstra模板!!

發布時間:2025/4/5 c/c++ 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PAT甲级1131 Subway Map (30分):[C++题解]堆优化dijkstra、单源最短路、地铁地图、巧妙地建图套dijkstra模板!! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 題目分析
    • 題目鏈接

題目分析

原題:




來源:acwing

分析:

建圖:所有能走到的點之間建立一條邊,比如下面一條地鐵線路有4站,它們是相通的,兩兩之間建一條邊,邊權是經過的站點數。

下面考慮一下使用哪種最短路算法。

每條線路最多100個點,如上這樣建圖,最多的邊數為:C1002<5000<10000C_{100}^2 < 5000 < 10000C1002?<5000<10000條邊;最多有100條路線,最多10000個點最多建立 10000 × 100 = 1e6條邊,即100萬條邊。

使用樸素的dijkstra算法會超時O(n2)=100002=108超時O(n^2) = 10000^2=10^8超時O(n2)=100002=108, 需要使用堆優化版本的dijkstra()算法O(m×logn)=1e6×log10000=4e6不會超時O(m\times logn) =1e6 \times log10000 = 4e6不會超時O(m×logn)=1e6×log10000=4e6

限制1s的話,運算1e8次差不多;現在限制是0.4s,差不多運算 5e7次才不超時。

看題意:第一點,首先輸出最少需要停靠的站點數量,這就是在我們的建圖中最短路(每條邊有權重,權重等于結點之間的站點數);第二點,如果最快線路不唯一,則輸出換乘次數最少的線路,換乘次數最少,在我們的圖中等價于邊數最少,因為同一條路線上的點只有一條邊,邊數越多,表示經過的線路越多。

綜上:最短路取決于邊權大小;換乘少取決于邊數少。
建圖如下:下圖有兩條地鐵線路,分別有4個站點和5個站點,并且有1個換乘站,所以下面的幾個點都是連通的,可以通過換乘到達。我們的建圖原則是:在一條線路上的任意兩站之間建一條邊,邊權為兩者之間的站點數量。


堆優化版的dijkstra算法模板請移步最短路[Dijkstra和堆優化的Dijkstra][Bellman-Ford和SPFA][Floyd最短路](更新中)

ac代碼

#include<bits/stdc++.h> using namespace std; const int N =10010 , M =1e6+10; typedef pair<int,int> PII; # define x first #define y secondint n , h[N],e[M],ne[M],w[M],idx; int line[M];//每條邊屬于幾號線 int stops[N];//站點 int dist[N];// int cnt[N]; //記錄經過的邊數;換成少===經過的邊數少 bool st[N]; int pre[N]; string info[N];//記錄地鐵線路信息/* 鄰接表建邊:建立a到b的邊 a和b是站點 c是權值,表示中間隔了幾站 id是線路號line */void add(int a ,int b, int c, int id){e[idx] =b,w[idx] =c,line[idx] =id, ne[idx] = h[a] ,h[a] =idx ++; }//4位站牌號,不足補上 string get_number(int x){string res = to_string(x);while(res.size() <4) res = '0' + res;return res;}void dijkstra(int start, int end){memset(dist, 0x3f, sizeof dist);memset(cnt, 0 ,sizeof cnt);memset(st, 0 ,sizeof st);dist[start] = 0 ,cnt[start] =0;priority_queue<PII, vector<PII> ,greater<PII>> heap;//小根堆heap.push({0,start}); //加入起點{距離,編號}while(heap.size()){auto t = heap.top();heap.pop();int ver =t.y; //節點編號if(ver == end) break;if(st[ver]) continue;st[ver] =true;for(int i=h[ver]; i!= -1; i = ne[i]){int j = e[i];//距離更短,更新if(dist[j] > dist[ver] + w[i]){dist[j] =dist[ver] +w[i];cnt[j] =cnt[ver] +1; //走過的邊數pre[j] = ver;info[j] ="Take Line#"+to_string(line[i])+ " from "+ get_number(ver) +" to "+ get_number(j) +".";heap.push({dist[j] ,j});}//距離相同,看看else if( dist[j] == dist[ver] +w[i]){if(cnt[j] > cnt[ver] + 1){cnt[j] =cnt[ver] +1;pre[j] = ver;info[j] ="Take Line#"+to_string(line[i])+ " from "+ get_number(ver) +" to "+ get_number(j) +".";heap.push({dist[j],j});}}}}cout<< dist[end]<<endl;vector<string > path;//倒序存入pathfor(int i = end; i != start; i =pre[i]) path.push_back(info[i]);for(int i =path.size()-1; i>=0 ;i--) cout<< path[i ] <<endl; }int main() {cin >> n;memset(h ,-1 ,sizeof h); //鄰接表初始化for(int i =1; i<= n; i++){ //n條線路int m;//站點cin >> m;for(int i = 0; i< m; i++) cin >> stops[i];//同一條線路上的站點,因為都是連通的,兩兩之間建邊for(int j = 0; j< m; j++){for(int k =0; k< j; k++){int length;//如果不是環路if(stops[0] !=stops[m-1]) length = j - k;//如果是環路,取兩邊短的else length = min(j - k , m-1 - j +k);//建邊的時候把長度也建好了,等于之間走了幾站:lengthadd(stops[j],stops[k],length, i); add(stops[k],stops[j], length ,i);}}}int m;cin >> m;while(m--){int start ,end;cin >> start >> end;dijkstra(start, end);}}

題目鏈接

PAT甲級1131 Subway Map (30分)

https://www.acwing.com/problem/content/1626/

總結

以上是生活随笔為你收集整理的PAT甲级1131 Subway Map (30分):[C++题解]堆优化dijkstra、单源最短路、地铁地图、巧妙地建图套dijkstra模板!!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。