【HDU - 6290】 奢侈的旅行 (对题目预处理 + DIjkstra最短路)
題干:
高玩小Q不僅喜歡玩尋寶游戲,還喜歡一款升級養成類游戲。在這個游戲的世界地圖中一共有nn個城鎮,編號依次為11到nn。?
這些城鎮之間有mm條單向道路,第ii?條單項道路包含四個參數ui,vi,ai,biui,vi,ai,bi,表示一條從uiui號城鎮出發,在vivi號城鎮結束的單向道路,因為是單向道路,這不意味著小Q可以從vivi沿著該道路走到uiui。小Q的初始等級levellevel為11,每當試圖經過一條道路時,需要支付cost=log2level+ailevelcost=log2?level+ailevel點積分,并且經過該道路后,小Q的等級會提升aiai級,到達level+ailevel+ai級。但是每條道路都會在一定意義上歧視低消費玩家,準確地說,如果該次所需積分cost<bicost<bi,那么小Q不能經過該次道路,也不能提升相應的等級。?
注意:本游戲中等級為正整數,但是積分可以是任意實數。?
小Q位于11號城鎮,等級為11,現在為了做任務要到nn號城鎮去。這將會是一次奢侈的旅行,請寫一個程序幫助小Q找到需要支付的總積分最少的一條路線,或判斷這是不可能的。
Input
第一行包含一個正整數T(1≤T≤30)T(1≤T≤30),表示測試數據的組數。?
每組數據第一行包含兩個整數n,m(2≤n≤100000,1≤m≤200000)n,m(2≤n≤100000,1≤m≤200000),表示城鎮數和道路數。
接下來mm行,每行四個整數ui,vi,ai,bi(1≤ui,vi≤n,ui≠vi,0≤ai≤109,0≤bi≤60)ui,vi,ai,bi(1≤ui,vi≤n,ui≠vi,0≤ai≤109,0≤bi≤60),分別表示每條單向道路。
Output
對于每組數據,輸出一行一個整數,即最少所需的總積分的整數部分,如:4.99994.9999輸出44,1.01.0輸出11。若不存在合法路線請輸出?1?1。
Sample Input
1 3 3 1 2 3 2 2 3 1 6 1 3 5 0Sample Output
2解題報告:
? ? ? 具體的題目的分析 ?博客?? 。總之就是把公式化簡一下(即考慮從1號點開始到各個點的cost)發現根本用不到level而是只跟ai有關,所以只需要dis數組中是ai的和的最小值即可,最后答案中在取個log2,就是答案了。判斷b的時候(即是否能走這條線)剛開始理解錯了,理解成了跟level有關,但是其實沒關系,只跟ai有關,而ai更開始也理解錯了,,不是從起點到該點的level和,而是這條邊自帶的權值!總之還是沒讀好題。。而且判斷b的時候的cost也是該邊的cost而非從起點過來的cost!通過公式化簡(指數函數的運算)就很容易求出該邊的cost和bi之間的關系來進行continue;
剛開始還覺得不同路徑走的時候level也不一樣啊比如我都是走到5號點,一個是2號(比如這個點level是3)過來的,一個是4號點過來的(可能這個點的level是2),所以相當于有很多權值的限制啊!但是比賽的時候就得反過來想啊,,這么麻煩的話怎么可能有ac的呢?所以肯定有化簡的方法,,比如從公式入手,,發現這個對數函數剛好可以都約掉中間項所以只和終點有關,和路徑無關。還是要多做題多總結啊!給公式的題往往可以公式入手!
AC代碼:
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAXN = 100000 + 5; const int MAXE = 200000 + 5;int n,m; int cnt; int head[MAXN] ; ll dis[MAXN]; bool vis[MAXN]; struct Edge {int to;ll a;ll b;int ne; } e[MAXE]; struct Point {int pos;ll cost;Point(){}Point(int pos,ll cost):pos(pos),cost(cost){}bool operator<(const Point b)const {return cost > b.cost;} }; void add(int u,int v,ll a,ll b) {e[cnt].to = v;e[cnt].a = a;e[cnt].b = b;e[cnt].ne = head[u];head[u] = cnt++; } void Dijkstra(int st) {priority_queue<Point > pq;dis[st] = 1;pq.push(Point(st,1));while(!pq.empty()) {Point cur = pq.top();pq.pop();if(vis[cur.pos] == 1) continue;vis[cur.pos] = 1;for(int i = head[cur.pos]; i!=-1; i=e[i].ne) {if(1 + e[i].a/cur.cost < pow(2,e[i].b)) continue;//這里的pow其實可以找個數組預處理一下 if(dis[cur.pos] + e[i].a < dis[e[i].to] ) {dis[e[i].to] = cur.cost+ e[i].a;//把dis[cur.pos]換成cur.cost行嗎? pq.push(Point(e[i].to,dis[e[i].to])); }}} } int main() {int t;cin>>t;//頂點1~nint u,v;ll a,b;while(t--) {cnt = 0;memset(vis,0,sizeof(vis));memset(head,-1,sizeof(head));//別想當然寫0scanf("%d%d",&n,&m); for(int i = 1; i<=n; i++) dis[i] = LLONG_MAX;//別把這一步放在讀入n、m前面。。。 while(m--) {scanf("%d%d%lld%lld",&u,&v,&a,&b);add(u,v,a,b);}Dijkstra(1); // printf("%lld\n\n\n",dis[n]); printf("%.0f\n",dis[n] == LLONG_MAX ? -1 : floor(log2(dis[n])));}return 0 ; }總結:
? ?別把初始化放在讀入m、n前面。。
Dijkstra 中//把dis[cur.pos]換成cur.cost行嗎? ? ?是可以的,但是還是寫前者比較好,因為Point結構體中這個變量其實就是儲存一下為了排序的,不是為了用的。。。
總結
以上是生活随笔為你收集整理的【HDU - 6290】 奢侈的旅行 (对题目预处理 + DIjkstra最短路)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 互联网存款被判“死刑”,储户的存款何处安
- 下一篇: 【ZOJ - 2724】【HDU - 1