【题解】
求两个变量构成的最优值,可以考虑限制一个变量,最优化另一个
观察此题,可以得到这样一个思路:
假设已知答案中的Ai的最大值不超过x,只需最小化1到n路径上的Bi的最大值
不难想到二分这个Ai的上限x
更新方式为SPFA,即,设d[i]为:只考虑Ai<=x的边,从1到i的路径上BiMax的最小值
然而这样的话,对于每个x,d数组都要重新求
不如我们按Ai从小到大加边,随着加边来更新 BiMax 的最小值,这样d[i]只需在原有的基础上更新即可,不必全部重新求
每加入一条边,就将它的两个端点加入队列,用它们来更新其他点的d值
最后,更新答案的方式为:if(ans>ta[i]+d[n]) ans=ta[i]+d[n]; 因为若d[n]变得更优了,一定是因为走了新加入的边的缘故,因此AiMax必定是新加入变的A值
复杂度不会分析,一个数据结构题就这么被水过去了,不知我现在的水平,要是在考场上,能不能机智地拿上这分 //flag不敢立
在B站的时间、代码量排名中似乎比较优秀?
【代码】
#include<stdio.h> #include<stdlib.h> #define INF 1000000 int tu[100005],tv[100005],tb[100005],ta[100005]; int v[200005],A[200005],B[200005],first[50005],next[200005],d[50005],hash[50005],q[10000005]; int e=0; int max(int a,int b) { if(a>b) return a; return b; } void jh(int* a,int* b) { int t=*a; *a=*b; *b=t; } void tj(int x,int y,int ta,int tb) { v[++e]=y; A[e]=ta; B[e]=tb; next[e]=first[x]; first[x]=e; } void kp(int low,int high) { int i=low,j=high,mid=ta[(i+j)/2]; while(i<j) { while(ta[i]<mid) i++; while(ta[j]>mid) j--; if(i<=j) { jh(&tu[i],&tu[j]); jh(&tv[i],&tv[j]); jh(&ta[i],&ta[j]); jh(&tb[i],&tb[j]); i++; j--; } } if(j>low) kp(low,j); if(i<high) kp(i,high); } int main() { int n,m,i,j,head,tail,ans=INF; scanf("%d%d",&n,&m); for(i=1;i<=m;i++) scanf("%d%d%d%d",&tu[i],&tv[i],&ta[i],&tb[i]); kp(1,m); for(i=2;i<=n;i++) d[i]=INF; for(i=1;i<=m;i++) { tj(tu[i],tv[i],ta[i],tb[i]); tj(tv[i],tu[i],ta[i],tb[i]); head=0; tail=2; q[0]=tu[i]; q[1]=tv[i]; hash[tu[i]]=hash[tv[i]]=i; while(head<tail) { for(j=first[q[head]];j!=0;j=next[j]) if( d[v[j]] > max(d[q[head]],B[j]) ) { d[v[j]] = max(d[q[head]],B[j]); if(hash[v[j]]!=i) { q[tail++]=v[j]; hash[v[j]]=i; } } hash[q[head++]]=0; } if(ans>ta[i]+d[n]) ans=ta[i]+d[n]; } if(ans!=INF) printf("%d",ans); else printf("-1"); return 0; }