洛谷P1462 通往奧格瑞瑪的道路
阿新 • • 發佈:2018-12-09
洛谷P1462 通往奧格瑞瑪的道路
題目背景
在艾澤拉斯大陸上有一位名叫歪嘴哦的神奇術士,他是部落的中堅力量
有一天他醒來後發現自己居然到了聯盟的主城暴風城
在被眾多聯盟的士兵攻擊後,他決定逃回自己的家鄉奧格瑞瑪
題目描述
在艾澤拉斯,有\(n\)個城市。編號為\(1,2,3,...,n\)。
城市之間有\(m\)條雙向的公路,連線著兩個城市,從某個城市到另一個城市,會遭到聯盟的攻擊,進而損失一定的血量。
每次經過一個城市,都會被收取一定的過路費(包括起點和終點)。路上並沒有收費站。
假設1為暴風城,\(n\)為奧格瑞瑪,而他的血量最多為\(b\),出發時他的血量是滿的。
歪嘴哦不希望花很多錢,他想知道,在可以到達奧格瑞瑪的情況下,他所經過的所有城市中最多的一次收取的費用的最小值是多少。
輸入輸出格式
輸入格式:
第一行3
個正整數,\(n\),\(m\),\(b\)。分別表示有\(n\)個城市,\(m\)條公路,歪嘴哦的血量為\(b\)。
接下來有\(n\)行,每行1
個正整數,\(f_i\)。表示經過城市\(i\),需要交費\(f_i\)元。
再接下來有\(m\)行,每行3
個正整數,\(a_i\),\(b_i\),\(c_i\)\((1 \leq a_i,b_i \leq n)\)。表示城市\(a_i\)和城市\(b_i\)之間有一條公路,如果從城市\(a_i\)到城市\(b_i\),或者從城市\(b_i\)到城市\(a_i\),會損失\(c_i\)的血量。
輸出格式:
僅一個整數,表示歪嘴哦交費最多的一次的最小值。
如果他無法到達奧格瑞瑪,輸出AFK
。
思路
二分答案
二分交費的最小值\(k\)
然後判斷是否可行的方法是:在圖中刪去所有費用大於\(k\)的點,再跑最短路,如果最短路的值大於歪嘴哦的血量,那就不可行,否則可行
CODE
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define MAXN 10010 #define MAXM 200010 struct Node{ int u,v,w; Node(){} Node(int u,int v,int w):u(u),v(v),w(w){} }p[MAXM]; struct R{ int id,dis; R(){} R(int id,int dis):id(id),dis(dis){} bool operator < (const R &a) const{ return dis>a.dis; } }tmp; int head[MAXN],Next[MAXM],dis[MAXN],cost[MAXN]; priority_queue<R> mque; bool vis[MAXN]; int i,j,k,m,n,u,v,w,tot,l,r,mid,ans,b,upborder; bool flag; void addNode(int u,int v,int w){ p[++tot]=Node(u,v,w); Next[tot]=head[u],head[u]=tot; p[++tot]=Node(v,u,w); Next[tot]=head[v],head[v]=tot; } bool dijkstra(int src,int goal){ if(cost[src]>mid) return false; while(!mque.empty()) mque.pop(); memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[src]=0; mque.push(R(src,0)); while(!mque.empty()){ tmp=mque.top(); mque.pop(); if(vis[tmp.id]) continue; vis[tmp.id]=true; for(register int i=head[tmp.id];i+1;i=Next[i]){ if(cost[p[i].v]<=mid&&dis[p[i].u]+p[i].w<dis[p[i].v]){ dis[p[i].v]=dis[p[i].u]+p[i].w; mque.push(R(p[i].v,dis[p[i].v])); } } } if(dis[goal]<b) return true; return false; } void solve(){ l=0,r=1000000000; flag=false; while(l<r){ mid=(l+r)>>1; if(dijkstra(1,n)){ r=mid; flag=true; }else{ l=mid+1; } } } int main(){ scanf("%d%d%d",&n,&m,&b); memset(head,-1,sizeof(head)); tot=-1; upborder=0; for(i=1;i<=n;i++){ scanf("%d",cost+i); } for(i=1;i<=m;i++){ scanf("%d%d%d",&u,&v,&w); addNode(u,v,w); upborder=max(upborder,w); } solve(); if(flag){ printf("%d\n",l); }else{ printf("AFK\n"); } return 0; }