codeforces 938D Buy a Ticket 有初值的Dijkstra、有趣的题目
題意
給出一些城市電影票的價格,以及城市之間交通的路費,詢問每一個城市怎樣才能花最少的錢看到電影(看完電影還要再回來)。
題解
這是一道不太難但是挺有趣的題目。
我們這樣想,每個城市只需要查看票價比他更便宜的城市,來更新本城市的票價就可以了,是不是想到了Dijkstra求最短路的思路。
這樣的話,我們先從票價最便宜的城市開始,從這個城市出發,更新其他所有城市的票價(新票價=原票價+2*路費),然后本城市的票價就求出來了。
再重復上述操作,也就是重新找一個票價最低的城市,然后更新其他城市的票價,這樣就ok啦。
這道題還有一個巨坑,會卡掉一部分人的Dijkstra的代碼,比如我,TLE。
為什么呢?
很多人寫代碼像這樣
這樣寫過不了第18組測試數據,因為這樣一組極端數據就卡掉了
n = 200000,m = 199999
200000 1 2
200000 2 4
200000 3 6
200000 4 8
…
假如優先隊列運行時訪問點的順序是1、2、3、…、200000
那么優先隊列里面會有199999個(dist[200000],200000)點對。
而每有一個這樣的點對,都將會把200000的邊全都遍歷一邊。
時間復雜度就會增加到2000002200000^22000002顯然爆炸,所以要把優先隊列里面多余點對刪掉。
在u點被取出時,增加一句。
if(wa[u] < p.first) continue;
至此,這道題就AC啦。
####代碼
#include <cstdio> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <cstring> using namespace std; typedef long long ll; typedef pair<ll,int> pli; const int maxn = 2e5+10; priority_queue<pli,vector<pli>,greater<pli> > pq; ll wa[maxn]; struct edge{int u,v,nxt;ll w; }es[maxn<<1]; int head[maxn],vis[maxn]; int cnt = 0,n,m; void addedge(int u,int v,ll w){es[cnt].u = u,es[cnt].v = v,es[cnt].nxt = head[u],es[cnt].w = w;head[u] = cnt++; } void solve(){while(!pq.empty()){pair<ll,int> p = pq.top();pq.pop();int u = p.second;if(wa[u] < p.first) continue;for(int e = head[u];e != -1;e = es[e].nxt){int v = es[e].v;ll w = es[e].w;if(wa[v] > 2*w+wa[u]){wa[v] = wa[u]+2*w;pq.push(make_pair(wa[v],v));}}} } int main(){memset(head,-1,sizeof(head));cin>>n>>m;for(int i = 0;i < m;++i){int u,v;ll w;scanf("%d%d%lld",&u,&v,&w);addedge(u,v,w);addedge(v,u,w);}for(int i = 1;i <= n;++i) {ll w;scanf("%lld",&w);wa[i] = w;pq.push(make_pair(w,i));}solve();for(int i = 1;i <= n;++i)printf("%lld ",wa[i]);return 0; }總結
以上是生活随笔為你收集整理的codeforces 938D Buy a Ticket 有初值的Dijkstra、有趣的题目的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: codeforces 932E Team
- 下一篇: bushi是什么梗 bushi是什么意思