码迷,mamicode.com
首页 > 其他好文 > 详细

通往奥格瑞玛的道路——二分加SPFA

时间:2017-11-02 22:04:07      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:div   display   code   out   sizeof   这不   cst   method   include   

  因为所求的最优解不关乎到达目的地时的血量,所以我们只需考虑能否到达和如何取到最优解这两个问题。如果用贪心之类的方法,可以想象这个题目会变得无比复杂,所以我们换一种思路想想。题目要求的是在能够到达奥格瑞玛的情况下,一路上所花费的过路费的最大值的最小可能值。我们可以想象,如果给定一个过路费的最大值Max,那么就相当于是从图中删去了过路费大于Max 的所有点。我们显然可以用单源最短路算法判断,删去一部分点后歪嘴哦能否到达奥格瑞玛,即从点1 到点n 的距离是否大于等于数据中给出的初始血量b。这样一来,更不难想到,Max 的值越小,歪嘴哦能成功回城的“希望”就越小,因为Max 的值越小,图中的点越少。那么,我们就可以从所有城市的过路费数组中二分出答案了,只需用SPFA 简单验证解的可行性即可。另外再多说几句,看我的代码就可以知道,歪嘴哦不能回到奥格瑞玛,即输出“AFK”的情况有且仅有一种:不论Max 怎么大,他都无法回到奥格瑞玛,这不难想到,采用预判的方式判断无解还可以稍微减少处理数据的复杂程度。并且,Max 的值一定要大于等于点1 和点n 的过路费。

技术分享
 1 #include<queue>
 2 #include<vector>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cstdio>
 8 using namespace std;
 9 const long long N=11111,INF=0x3fffffffffffffff;
10 long long n,m,b,f[N],val[N],l,r,res;
11 vector<long long> gr[N],dis[N];
12 
13 bool check(long long v){
14     long long d[N];
15     bool inq[N];
16     queue<long long> q;
17     memset(inq,0,sizeof inq);memset(d,0x3f,sizeof d);
18     q.push(1);inq[1]=true;d[1]=0;
19     while(!q.empty()){
20         long long x=q.front();q.pop();inq[x]=false;
21         for(long long i=0;i<gr[x].size();i++)
22             if(f[gr[x][i]]<=v&&d[x]+dis[x][i]<d[gr[x][i]]){
23                 d[gr[x][i]]=d[x]+dis[x][i];
24                 if(!inq[gr[x][i]])q.push(gr[x][i]),inq[gr[x][i]]=true;
25             }
26     }
27     return f[n]<=v&&d[n]<b;
28 }
29 
30 int main(){
31     cin>>n>>m>>b;
32     for(long long i=1;i<=n;i++){scanf("%lld",f+i);r+=f[i];val[i]=f[i];}
33     sort(val+1,val+1+n);
34     
35     while(m--){
36         long long x,y,v;scanf("%lld%lld%lld",&x,&y,&v);
37         gr[x].push_back(y);dis[x].push_back(v);
38         gr[y].push_back(x);dis[y].push_back(v);
39     }
40     
41     if(!check(INF)){
42         cout<<"AFK"<<endl;
43         return 0;
44     }
45     
46     while(val[l]<max(f[1],f[n]))l++;l--;
47     r=n;
48     while(l<=r){
49         m=(l+r)>>1;
50         if(check(val[m]))r=m-1,res=val[m];
51         else l=m+1;
52     }
53     cout<<res<<endl;
54     return 0;
55 }
Method_01

  洛谷 664ms

通往奥格瑞玛的道路——二分加SPFA

标签:div   display   code   out   sizeof   这不   cst   method   include   

原文地址:http://www.cnblogs.com/duskfire/p/7774553.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!