[Luogu1462]通往奥格瑞玛的道路
题目大意:
一个n个点,m条边的图,每个边有一个边权,每个点也有一个点权。
现在要找一条从1到n的路径,保证边权和不超过b的情况下,最大点权尽量小。
问最大点权最小能是多少?
思路:
二分答案,然后Dijkstra跑最短路判断可行性。
假设二分到的最大点权为m,那么最短路中跑到点权>m的直接忽略,对于长度大于b的最短路也直接忽略。
对点权离散化后二分会快不少。
1 #include<cstdio> 2 #include<cctype> 3 #include<vector> 4 #include<algorithm> 5 #include<functional> 6 #include<ext/pb_ds/priority_queue.hpp> 7 inline int getint() { 8 register char ch; 9 while(!isdigit(ch=getchar())); 10 register int x=ch^'0'; 11 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 12 return x; 13 } 14 const int inf=0x7fffffff; 15 const int N=10001; 16 int f[N],n,m,b; 17 struct Edge { 18 int to,w; 19 }; 20 std::vector<Edge> e[N]; 21 inline void add_edge(const int &u,const int &v,const int &w) { 22 e[u].push_back((Edge){v,w}); 23 e[v].push_back((Edge){u,w}); 24 } 25 int d[N]; 26 struct Vertex { 27 int id,dis; 28 bool operator > (const Vertex &another) const { 29 return dis>another.dis; 30 } 31 }; 32 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > q; 33 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> >::point_iterator p[N]; 34 inline void dijkstra(const int &m) { 35 p[1]=q.push((Vertex){1}); 36 for(register int i=2;i<=n;i++) { 37 p[i]=q.push((Vertex){i,d[i]=b+1}); 38 } 39 while(q.top().dis<=b) { 40 const int x=q.top().id; 41 for(register unsigned i=0;i<e[x].size();i++) { 42 const int &y=e[x][i].to; 43 if(f[y]>m) continue; 44 if(d[x]+e[x][i].w<d[y]) { 45 q.modify(p[y],(Vertex){y,d[y]=d[x]+e[x][i].w}); 46 } 47 } 48 q.modify(p[x],(Vertex){0,b+1}); 49 } 50 q.clear(); 51 } 52 inline bool check(const int &m) { 53 dijkstra(m); 54 return d[n]!=b+1; 55 } 56 int v[N]; 57 int main() { 58 n=getint(),m=getint(),b=getint(); 59 for(register int i=1;i<=n;i++) { 60 v[i]=f[i]=getint(); 61 } 62 v[0]=inf; 63 std::sort(&v[0],&v[n+1]); 64 for(register int i=1;i<=m;i++) { 65 const int &u=getint(),&v=getint(),&w=getint(); 66 add_edge(u,v,w); 67 } 68 int l=std::lower_bound(&v[0],&v[n+1],std::max(f[1],f[n]))-v,r=n; 69 while(l<r) { 70 const int mid=(l+r)>>1; 71 if(check(v[mid])) { 72 r=mid; 73 } else { 74 l=mid+1; 75 } 76 } 77 if(r!=n) { 78 printf("%d\n",v[r]); 79 } else { 80 puts("AFK"); 81 } 82 return 0; 83 }