「省选联考2020B-丁香之路」题解

P6628 [省选联考 2020 B 卷] 丁香之路

sol

这是一个无向完全图,不难想到走一条欧拉路径必然不劣。

欧拉路径的特点为除了起点与终点度数为奇,其余度数为偶,那么提前给起点终点度数更新 \(1\) 就可以方便处理奇偶性问题。具体地,我们现在要连新边使得每个点度数均为偶数。也可以理解为转化为欧拉回路问题。

考虑贪心,首先我们忽略度数为 \(0\) 的点,对于剩下所有度数为奇的点,两两相邻连边显然可以最小化代价不劣,于是我们把原图连成了多个合法连通块。接下来我们要使得全图连通,最小生成树一下即可,每条边一来一回连两次,故这一步产生的代价就是最小生成树边权和两倍。

更详细地解释“两两相邻连边不劣”,多手摸几个图就能看出,只有端点有交错的连边才需要放在一起考虑,端点不交错的分成两部分最后来 MST 不劣。对于端点有交错的连边,显然必然存在偶数个奇度点,那么贪心地两两相邻连边显然可以最小化代价。值得注意的是,这里并不是两个奇度点直接连边,而实际意义上可能在其间的某些偶度点停靠,代价是一样的,实际意义上连通了这些偶度点与外面的奇度点,不劣。

code

int n,m,s;
int dg[N];
int ans;

struct DSU{
    int fa[N];
    void init(){rep(i,1,n)fa[i]=i;}
    int find(int x){if(fa[x]!=x)fa[x]=find(fa[x]);return fa[x];}
    void merge(int a,int b){a=find(a),b=find(b);fa[a]=b;}
    bool same(int a,int b){return find(a)==find(b);}
}ini,dsu;

inline void Main(){
    read(n,m,s);
    ini.init();
    rep(i,1,m){
        int a,b;read(a,b);
        ++dg[a],++dg[b];
        ans+=abs(a-b);
        ini.merge(a,b);
    }
    rep(i,1,n){
        ++dg[s],++dg[i];
        int res=ans;
        dsu=ini;
        int lst=0;
        rep(i,1,n){
            if(lst){
                ++res;
                dsu.merge(i,i-1);
                if(dg[i]&1)lst=0;
            }else if(dg[i]&1)lst=i;
        }
        vec<pair<int,pii>> e;
        lst=0;
        rep(i,1,n)if(dg[i]){
            if(lst&&!dsu.same(lst,i))e.pub({i-lst,{dsu.find(i),dsu.find(lst)}});
            lst=i;
        }
        sort(e.begin(),e.end());dsu.init();
        for(auto i:e)if(!dsu.same(i.sec.fir,i.sec.sec))dsu.merge(i.sec.fir,i.sec.sec),res+=i.fir*2;
        put(res,' ');
        --dg[s],--dg[i];
    }
}
posted @ 2025-07-22 16:17  LastKismet  阅读(8)  评论(0)    收藏  举报