bzoj4398: 福慧双修

Posted ccz181078

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4398: 福慧双修相关的知识,希望对你有一定的参考价值。

正边权无向图,一条边两个方向权值不一定相同,求经过点1的最小简单环

简单环包含了点1的一条出边和一条入边,且这两条边不同,因此可以枚举这两条边的编号的二进制表示中哪一位不同,用最短路求此时的最优解,时间复杂度$O(mlog^2m)$

#include<bits/stdc++.h>
using std::swap;
using std::vector;
using std::priority_queue;
const int N=40007,inf=1000000000;
int _(){
    int x=0,c=getchar();
    while(c<48)c=getchar();
    while(c>47)x=x*10+c-48,c=getchar();
    return x;
}
int n,m;
struct edge{
    int to,v;
    bool operator<(edge e)const{return v>e.v;}
};
int l[N],ans=inf;
priority_queue<edge>q;
vector<edge>es[N],eS,eT;
bool ed[100007];
void mins(int&a,int b){if(a>b)a=b;}
void cal(){
    q=priority_queue<edge>();
    for(int i=1;i<=n;++i)l[i]=inf;
    for(int i=0;i<eS.size();++i)if(ed[i]){
        edge w=eS[i];
        if(l[w.to]>w.v)q.push((edge){w.to,l[w.to]=w.v});
    }
    while(q.size()){
        edge w=q.top();q.pop();
        if(w.v>=ans)break;
        if(w.v!=l[w.to])continue;
        for(int i=0;i<es[w.to].size();++i){
            edge u=es[w.to][i];
            if(l[u.to]>w.v+u.v)q.push((edge){u.to,l[u.to]=w.v+u.v});
        }
    }
    for(int i=0;i<eT.size();++i)if(!ed[i]){
        edge w=eT[i];
        mins(ans,l[w.to]+w.v);
    }
}
int main(){
    n=_(),m=_();
    for(int i=0,a,b,v1,v2;i<m;++i){
        a=_(),b=_(),v1=_(),v2=_();
        if(a==b)continue;
        if(a==1||b==1){
            if(b==1)swap(a,b),swap(v1,v2);
            eS.push_back((edge){b,v1});
            eT.push_back((edge){b,v2});
        }else{
            es[a].push_back((edge){b,v1});
            es[b].push_back((edge){a,v2});
        }
    }
    for(int t=1;t<eS.size();t<<=1){
        for(int i=0;i<eS.size();++i)ed[i]=i&t;
        cal();
        for(int i=0;i<eS.size();++i)ed[i]^=1;
        cal();
    }
    printf("%d\n",ans);
    return 0;
}

 

以上是关于bzoj4398: 福慧双修的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4398: 福慧双修

BZOJ2407/4398探险/福慧双修 最短路建模

不会的图论题

福慧双修(both)

CS4398音频解码替代芯片DP4398完全兼容DAC解码

题解 P4398 [JSOI2008]Blue Mary的战役地图