「省选联考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];
}
}

浙公网安备 33010602011771号