【题解】
求两个变量构成的最优值,可以考虑限制一个变量,最优化另一个
假设已知答案中的Ai的最大值不超过x,只需最小化1到n路径上的Bi的最大值这是一个最短路问题,即,设d[i]为:只考虑Ai<=x的边,从1到i的路径上BiMax的最小值。那么对AiMax=x来说,答案就是x+d[t]。对每个x用SPFA求解最短路
然而这样的话,对于每个x,d数组都要重新求不如我们按Ai从小到大加边,随着加边来更新 BiMax 的最小值,这样d[i]只需在原有的基础上更新即可,不必全部重算
每加入一条边,就将它的两个端点加入队列,用它们来更新其他点的d值
最后,更新答案的方式为:if(ans>ta[i]+d[n]) ans=ta[i]+d[n]; 因为若d[n]变得更优了,一定是因为走了新加入的边的缘故,因此AiMax必定是新加入变的A值
复杂度不会分析,一个数据结构题就这么被水过去了,不知我现在的水平,要是在考场上,能不能机智地拿上这分 //flag不敢立
在BZOJ的时间、代码量排名中似乎比较优秀?
【代码】
#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;
}