[NOI2014]魔法森林
一条边有\(a_i,b_i\)两个权值 求\(1->n\)路径上\(a\)的最大值与\(b\)的最大值之和的最小
==有lct的做法 但是spfa动态加点的做法也很巧妙!
先将其按\(a\)从小到大排序 然后依次加入边
对于ans的每次更新 当ans第一次更新时说明在加入这条边后才存在\(1->n\)的路 而新加的这条边一定在\(1->n\)的路径上
之后的更新也差不多同理(寄几想一想为什么
每加入一条边 就只用从新加入的这条边的\(u,v\)来开始更新 不用跑完==
int dis[N],vis[N]; queue<int> q; void spfa(int a,int b){ vis[a]=vis[b]=1; q.push(a),q.push(b); while(!q.empty()){ int u=q.front();q.pop(),vis[u]=0; for(int i=head[u],v,w;i;i=e[i].nxt) if(dis[v=e[i].v]>Max(dis[u],w=e[i].w)){ dis[v]=Max(dis[u],e[i].w); if(!vis[v]) q.push(v),vis[v]=1; } } } int main(){ #ifndef ONLINE_JUDGE // freopen("in.txt","r",stdin); #endif rd(n),rd(m);ans=inf; memset(dis,inf,sizeof(dis)); for(int i=1,u,v,a,b;i<=m;++i) rd(u),rd(v),rd(a),rd(b),E[i]=(node){u,v,a,b}; sort(E+1,E+m+1,cmp); dis[1]=0; for(int i=1,u,v,w;i<=m;++i){ u=E[i].u,v=E[i].v,w=E[i].b; add(u,v,w),add(v,u,w); spfa(u,v); ans=Min(ans,dis[n]+E[i].a); } if(ans==inf) return puts("-1"),0; printf("%d",ans); return 0; }