牛牛选路径

约定:称度数为奇数的点为奇点,称度数为偶数的点为偶点。

贪心策略

对于每一个连通块,考虑以下两种情况:

  1. 如果不存在奇点,则选择点权最小的点作为头尾连接一条路径。

  2. 存在奇点,则必然有偶数个奇点,只需要选出这些奇点之间的最优匹配,

    而这个最优匹配就是:排序之后不断取最小值和最大值匹配。

证明

  1. 没有奇点时,可以直接提取一条欧拉回路。

  2. 存在奇点时,对于任何一个合法的匹配,均存在方案,使得以匹配为头尾的链组,将每条边覆盖奇数次。

    下面给出了一个合法的构造:

    1. 设匹配点集合为{ui,vi}i=1k\{u_i,v_i\}_{i=1}^k,在ui,viu_i,v_i之间连接一条虚边,记为eie_i,得到新图GG'

      容易在原图上找到某一条ui,viu_i,v_i之间的路径,记作pip_i

    2. GG'上求一个欧拉回路PP

      此时容易通过将eie_i替换为pip_i的操作将虚边实化,称实化的路径为额外路径,记实化的环为PP'

    3. 对于每一个ui,viu_i,v_i,其对应的路径为PP'删除pip_i这一段,容易发现路径的头尾是对应的。

      此时,PP'上的额外路径均比其他路径少被遍历了恰好一次(因为在其对应的ui,viu_i,v_i这里被删除了)。

    4. 如果PP'上的非额外路径被遍历了偶数次,则在某一条路径中,额外增加一段绕过一整个PP'的段。

    这样就保证了PP'上的非额外路径被遍历了奇数次;而额外路径被遍历了偶数次,不产生贡献;

    PP'上的非额外路径就对应了原图的所有边,故构造合法。

  3. 匹配的最优性:

    设排序之后的奇点点权为a1,a2,,a2ka_1,a_2,\cdots,a_{2k},容易由排序不等式得到证明:

    1. 如果有一个匹配u,vu,v,满足u,v>ku,v>k,那么就必然存在一个匹配u,vu',v'满足u,vku',v'\leq k

      由二元排序不等式auav+auavauav+auava_ua_v+a_{u'}a_{v'}\ge a_{u}a_{v'}+a_{u'}a_v,此时交换v,vv,v'总更优。

    2. 排除11的情况后,此时问题变成了对于每个iki\leq k,匹配一个j>kj>k

      那么可以直接分成[1,k],[k+1,2k][1,k],[k+1,2k]两个集合,由多元排序不等式得到最优解。

#include<bits/stdc++.h>
using namespace std;
#define M 100005
#define P 998244353 
int n,m,a[M],deg[M],sk[M];
vector<int>d[M];
bool cmp(int x,int y){
	return a[x]<a[y];	
}
int main(){
	int mx=0;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
	}
	for(int i=1,x,y;i<=m;++i){
		scanf("%d%d",&x,&y);
		d[x].push_back(y);
		d[y].push_back(x);
		deg[x]^=1;deg[y]^=1;
	}
	int cnt=0,ans=0;
	for(int i=1;i<=n;++i)if(deg[i])sk[++cnt]=i;
	if(cnt==0){
		ans=1e9;
		for(int i=1;i<=n;++i)ans=min(ans,a[i]*a[i]);
	}else{
		sort(sk+1,sk+cnt+1,cmp);
		for(int i=1;i<=cnt/2;++i)ans+=a[sk[i]]*a[sk[cnt-i+1]];
	}
	printf("%d",ans%P);
}