版权声明:未经作者本人允许禁止转载。 https://blog.csdn.net/jokerwyt/article/details/82946475
题目描述
分析
一个无向图存在欧拉回路当且仅当所有的点的度数为偶数,所以需要在每一对奇点之间连一条边然而观察这题这题的边权,发现所有比某条边小的边之和比这条边小。那也就是说最短路必定在最小生成树上。这就变成了最小生成树上的配对问题。只要保证不走重边,结果一定是一样的。一棵子树内假如是奇数那么会有一个点需要走一次向外连的边。
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 5e5+10, mo = 998244353;
int n,m;
int final[N],nex[N*2],to[N*2],w[N*2],tot;
int f[N];
void link(int x,int y,int ww) {
to[++tot] = y,nex[tot] = final[x],final[x] = tot;
w[tot] = ww;
}
int s[N],fa[N];
ll ans,d[N];
int gf(int x) {return fa[x]==0?x:fa[x]=gf(fa[x]);}
void dfs(int x,int q) {
s[x] = (d[x]&1);
for (int i = final[x]; i; i=nex[i]) {
int y = to[i]; if (y != f[x]) {
f[y]=x;
dfs(y,w[i]);
s[x]+=s[y];
}
}
ans = (ans + (s[x]&1) * q) % mo;
}
int main() {
freopen("travel.in","r",stdin);
// freopen("travel.out","w",stdout);
cin>>n>>m;
tot = 1;
ll x = 1,zzz = 0;
for (int i = 1; i <= m; i++) {
x = x * 2 % mo;
zzz = (zzz + x) % mo;
int u,v; scanf("%d %d",&u,&v);
d[u]++,d[v]++;
if (gf(u)!=gf(v)) {
fa[gf(u)] = gf(v);
link(u,v,x);
link(v,u,x);
}
}
dfs(1,0);
cout<<(ans+zzz)%mo<<endl;
}