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 }