luoguP1462通往奥格瑞玛的道路(二分答案+spfa)

题意

给出n个点m条边的无向图。

每条边有两个权值a,b;

问在保证从1到n的路径a权值和小于x时,路径上b权值最大值最小为多少。

(n≤10000,m≤50000,x≤1000000000)

题解

二分x,然后跑最短路判断。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 struct hhh{
  9     int nxt,to,w;
 10 }c[100001];
 11 queue<int> q;
 12 #pragma GCC optimize(2)
 13 /*inline void write(int x)
 14 {
 15      if(x<0) putchar('-'),x=-x;
 16      if(x>9) write(x/10);
 17      putchar(x%10+'0');
 18 }*/
 19 int cnt,book[60000],ans,maxx,l,r,head[60000],dis[60000],n,m,b,w[60000],u,v,k;
 20 bool flag;
 21 inline void add(register int u,register int v,register int w){
 22     cnt++;
 23     c[cnt].w=w;
 24     c[cnt].to=v;
 25     c[cnt].nxt=head[u];
 26     head[u]=cnt;
 27 }
 28 inline void spfa(register int ma){
 29     while(!q.empty()){
 30         register int u=q.front();
 31         q.pop();
 32         book[u]=0;
 33         for(register int i=head[u];i;i=c[i].nxt){
 34             register int v=c[i].to;
 35             if(!book[v]&&w[v]<=ma&&dis[v]>dis[u]+c[i].w&&dis[u]+c[i].w<=b){
 36                 dis[v]=dis[u]+c[i].w;
 37                 book[v]=1;
 38                 q.push(v);
 39                 if(v==1){
 40                     while(!q.empty())q.pop();
 41                     flag=true;
 42                     return;
 43                 }
 44             }
 45         }
 46     }
 47 }
 48 /*inline int read()
 49 {
 50      register int q=0;
 51     register int f=1;
 52     char ch=getchar();
 53     while(ch<'0'||ch>'9')
 54     {
 55         if(ch=='-') f=-1;
 56         ch=getchar();
 57     }
 58     while(!(ch<'0'||ch>'9'))
 59     {
 60         q=q*10+ch-'0';
 61         ch=getchar();
 62     }
 63     return q*f;
 64 }*/
 65 inline int read()
 66 {
 67     register int X=0,w=0; 
 68     char ch=0;
 69     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
 70     while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
 71     return w?-X:X;
 72 }
 73 
 74 int main(){
 75     n=read();m=read();b=read();
 76     for(register int i=1;i<=n;i++){
 77         w[i]=read();
 78         maxx=max(maxx,w[i]);
 79     }
 80     for(register int i=1;i<=m;i++){
 81         u=read(),v=read(),k=read();
 82         if(u==v)continue;
 83         add(u,v,k);
 84         add(v,u,k);
 85     }
 86     for(register int i=1;i<n;i++){
 87             dis[i]=1100000010;
 88     }
 89     q.push(n);
 90     book[n]=1;
 91     flag=false;
 92     spfa(1000000001);
 93     if(!flag){
 94         printf("AFK");
 95         return 0;
 96     }
 97     l=max(w[1],w[n]);
 98     r=maxx+1;
 99     while(l<=r){
100         for(register int i=1;i<n;i++){
101             dis[i]=1100000010;
102             book[i]=0;
103         }
104         flag=false;
105         int mid=(l+r)/2;
106         q.push(n);
107         book[n]=1;
108         spfa(mid);
109         if(flag)r=mid-1;
110         else l=mid+1;
111         ans=mid;
112         
113     }
114     printf("%d",l);
115     return 0;
116 }
View Code
原文地址:https://www.cnblogs.com/Xu-daxia/p/9416532.html