jzoj5895 【NOIP2018模拟10.5】旅游 (求欧拉回路,性质)

题目描述

在这里插入图片描述

分析

一个无向图存在欧拉回路当且仅当所有的点的度数为偶数,所以需要在每一对奇点之间连一条边然而观察这题这题的边权,发现所有比某条边小的边之和比这条边小。那也就是说最短路必定在最小生成树上。这就变成了最小生成树上的配对问题。只要保证不走重边,结果一定是一样的。一棵子树内假如是奇数那么会有一个点需要走一次向外连的边。

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值