【题解】[牛客网NOIP赛前集训营-提高组(第五场)]B.旅游 最小生成树

题目链接
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e5+10,mod=998244353;
inline int read()
{
	int s=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	if(f)s=-s;return s;
}
int n,m,hd[N],tot,fa[N],val[N],deg[N];
ll Pow[N],ans;
struct Edge{
	int v,nx;
	ll w;
}e[N<<1];
inline int Find(int x){return fa[x]==x?x:fa[x]=Find(fa[x]);}
inline void add(int u,int v,ll w)
{
	e[++tot].v=v;
	e[tot].w=w;
	e[tot].nx=hd[u];
	hd[u]=tot;
}
void dfs(int u,int f,ll len)
{
	for(int i=hd[u];i;i=e[i].nx)
	{
		int v=e[i].v;ll w=e[i].w;
		if(v!=f)dfs(v,u,w);
	}
	if(deg[u]%2)deg[u]++,deg[f]++,ans=(ans+len)%mod;
}
int main()
{
	//freopen("in.txt","r",stdin);
	n=read();m=read();
	for(int i=1;i<=n;i++)
	    fa[i]=i;
    Pow[0]=1;
	for(int i=1;i<=m+1;i++)
	    Pow[i]=Pow[i-1]*2%mod;
	ans=(Pow[m+1]-2)%mod;
	for(int i=1,u,v,fu,fv;i<=m;i++)
	{
		u=read();v=read();deg[u]++;deg[v]++;fu=Find(u);fv=Find(v);
		if(fu!=fv)
		{
			add(u,v,Pow[i]);add(v,u,Pow[i]);fa[fv]=fu;
		}
	}
	dfs(1,0,0);printf("%lld\n",ans);
	return 0;
}

总结