餓。其實我是一個不太喜歡寫部落格的人拉,因為覺得有點點浪費時間,特別是網上能搜到的題解,更懶得寫部落格了
可是還是寫下了這一題的題解部落格
因為自從今年cccc比賽後一直準備藍橋杯,昨天藍橋杯剛比完,今天想休息一下,也有點無聊
而且藍橋杯因為基本不怎麼考這種圖的,所以dijkstra這些的也基本沒複習,導致cccc到現在三周了,我今天無聊點開我PAT上的提交代碼發現自己居然有點看不懂自己寫的這題了= =還自己理了一下思路
而且網上對這題的題解也基本是粘個代碼就了事,還不如回顧下自己的代碼,廢話說的有點多,下面還是粘題目和題解吧
題目跳轉連結
L2-001. 緊急救援 時間限制 200 ms
記憶體限制 65536 kB
代碼長度限制 8000 B
判題程式 Standard 作者 陳越
作為一個城市的應急救援隊伍的負責人,你有一張特殊的全國地圖。在地圖上顯示有多個分散的城市和一些串連城市的快速道路。每個城市的救援隊數量和每一條串連兩個城市的快速道路長度都標在地圖上。當其他城市有緊急求助電話給你的時候,你的任務是帶領你的救援隊儘快趕往事發地,同時,一路上召集儘可能多的救援隊。
輸入格式:
輸入第一行給出4個正整數N、M、S、D,其中N(2<=N<=500)是城市的個數,順便假設城市的編號為0~(N-1);M是快速道路的條數;S是出發地的城市編號;D是目的地的城市編號。第二行給出N個正整數,其中第i個數是第i個城市的救援隊的數目,數字間以空格分隔。隨後的M行中,每行給出一條快速道路的資訊,分別是:城市1、城市2、快速道路的長度,中間用空格分開,數字均為整數且不超過500。輸入保證救援可行且最優解唯一。
輸出格式:
第一行輸出不同的最短路徑的條數和能夠召集的最多的救援隊數量。第二行輸出從S到D的路徑中經過的城市編號。數字間以空格分隔,輸出首尾不能有多餘空格。 輸入範例:
4 5 0 320 30 40 100 1 11 3 20 3 30 2 22 3 2
輸出範例:
2 600 1 3
其實這題就是個把所有都要考慮上的Dijkstra變形,也很符合CCCC很喜歡考資料結構的風格嘛(可是今年似乎就沒有啥資料結構的題= =)
要考慮的其實就是邊值最小,在邊值一樣的情況下考慮點值最大,然後考慮有幾條路徑到這的邊值是一樣最小的,同時記錄下路徑
下面貼下My Code,因為我是學校機房寫的提交的,現在在宿舍複製下來加了注釋,所以縮排變成了兩個空格= =無傷大雅
#include<iostream>#include<vector>#include<cstring>#include<set>#include<algorithm>#include<stack>using namespace std;int road[501][501],last[501],people[501],human[501],walk[501],rewalk[501];//road代表兩個城市的距離 last代表當前城市的上一條路是什麼,用來最後輸出最短路徑 people表示那個城市原本有多少人 human表示起點到目前城市能聚集多少個人 int main() //walk表示從起點到目前城市最短路徑是多少 rewalk表示從起點到目前城市的最短路徑走法有幾個 { int N,M,S,D; memset(road,-1,sizeof(road)); set<int> vis; cin>>N>>M>>S>>D; int tmpi; for(int i=0;i<N;i++) { cin>>tmpi; people[i]=tmpi; human[i]=tmpi; vis.insert(i); walk[i]=0x7fffffff; } last[S]=-1; walk[S]=0; rewalk[S]=1; for(int i=0;i<M;i++) { int be,en; cin>>be>>en; cin>>road[be][en]; road[en][be]=road[be][en]; }//這上面都是初始化資料 for(int now=S;vis.size()>0;vis.erase(now))//遍曆所有城市 { int Min=0x7fffffff; for(int i=0;i<N;i++)//每次選擇和當前城市相鄰中路徑最短的城市 { if(walk[i]<Min&&vis.count(i)==1) { now=i; Min=walk[i]; } } for(int i=now,j=0;j<N;j++) { if(road[i][j]!=-1) { if(walk[j]>road[i][j]+walk[now])//距離優先,如果距離近的優先更新資料 { walk[j]=road[i][j]+walk[now]; last[j]=now; human[j]=people[j]+human[now]; rewalk[j]=rewalk[now]; } else if(walk[j]==road[i][j]+walk[now])//如果距離相等,目前到的方案數+1 如果到的人數比之前的多 還是更新人數和從哪裡來的資料 { rewalk[j]+=rewalk[now]; if(human[j]<people[j]+human[now]) { last[j]=now; human[j]=people[j]+human[now]; } } } } } cout<<rewalk[D]<<" "<<human[D]<<endl; stack<int> st;//用棧,倒序輸出路徑 st.push(D); for(int i=D;last[i]!=-1;i=last[i]) st.push(last[i]); cout<<st.top(); st.pop(); while(!st.empty()) { cout<<" "<<st.top(); st.pop(); } return 0;}