洛谷 P1462 通往奥格瑞玛的道路(二分答案,堆优化dijkstra)
传送门
解题思路
首先看题目问题,求经过的所有城市中最多的一次收取的费用的最小值是多少。一看“最大值最小”就想到了二分答案。
在读一遍题目,就是二分收取的费用,然后对于每一个二分的费用,跑一边最短路,要求不经过>收取费用的城市,最后看一看能否在规定血量内走到终点。
想起来还是比较容易的,写起来要注意一下细节,注意二分的形式和用堆优化的dijkstra的写法。
悲惨的做题经历
今天凌晨,终于灵光一现,发现了问题——变量定义在主函数外面时不能直接用另一个变量来赋初值!!怪不得总是wrong answer!!
终于解决了烦了我三天的题了(终于可以睡觉了)QAQ
AC代码
1 #include<iostream> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstdio> 5 #include<cstring> 6 #include<queue> 7 using namespace std; 8 const int maxn=10005; 9 const int maxm=100005; 10 long long n,m,b,f[maxn],p[maxn],cnt,d[maxn],vis[maxn],dis[maxn]; 11 struct edge{ 12 int v,next; 13 long long value; 14 }e[maxm]; 15 void insert(int u,int v,long long value){ 16 cnt++; 17 e[cnt].v=v; 18 e[cnt].next=p[u]; 19 e[cnt].value=value; 20 p[u]=cnt; 21 } 22 struct node{ 23 int num; 24 long long value; 25 }; 26 bool operator <(node a,node b){ 27 return a.value>b.value; 28 } 29 bool dijkstra(long long mid){ 30 if(f[1]>mid||f[n]>mid) return false; 31 memset(dis,0x3f,sizeof(dis)); 32 memset(vis,0,sizeof(vis)); 33 priority_queue<node> q; 34 node tou; 35 tou.num=1; 36 tou.value=0; 37 dis[1]=0; 38 q.push(tou); 39 while(!q.empty()){ 40 node u=q.top(); 41 q.pop(); 42 if(vis[u.num]) continue; 43 vis[u.num]=1; 44 for(long long i=p[u.num];i!=-1;i=e[i].next){ 45 if(f[e[i].v]>mid) continue; 46 if(dis[u.num]+e[i].value<dis[e[i].v]){ 47 dis[e[i].v]=dis[u.num]+e[i].value; 48 node neww; 49 neww.num=e[i].v; 50 neww.value=dis[e[i].v]; 51 if(!vis[e[i].v])q.push(neww); 52 } 53 } 54 } 55 if(dis[n]>=b) return false; 56 return true; 57 } 58 long long l=1,r; 59 int main() 60 { 61 cin>>n>>m>>b; 62 r=n; 63 memset(p,-1,sizeof(p)); 64 for(int i=1;i<=n;i++){ 65 scanf("%lld",&f[i]); 66 d[i]=f[i]; 67 } 68 for(int i=1;i<=m;i++){ 69 long long u,v,value; 70 scanf("%lld%lld%lld",&u,&v,&value); 71 insert(u,v,value); 72 insert(v,u,value); 73 } 74 sort(d+1,d+1+n); 75 if(!dijkstra(d[n])){ 76 cout<<"AFK"; 77 return 0; 78 } 79 while(l<r){ 80 int mid=(l+r)/2; 81 if(dijkstra(d[mid])) r=mid; 82 else l=mid+1; 83 } 84 cout<<d[l]; 85 return 0; 86 }