[NOI2014]魔法森林[最短路 spfa]

[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;
}
上一篇:[NOI2014] 魔法森林 - Link Cut Tree


下一篇:【NOI2014】魔法森林