description
analysis
-
正解MST+思维
-
首先每条边的答案都要加上,然后做一次最小生成树
-
在MSTMSTMST里,如果以一个点为根的子树里有奇数个原图里的奇点,那么就再加上这个点到其父亲的边权
code
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#define MAXN 500005
#define MAXM MAXN*2
#define ll long long
#define mod 998244353ll
#define fo(i,a,b) for (register ll i=a;i<=b;++i)
#define fd(i,a,b) for (register ll i=a;i>=b;--i)
ll last[MAXM],next[MAXM],tov[MAXM],len[MAXM];
ll a[MAXN],f[MAXN],fa[MAXN];
ll n,m,tot,ans;
__attribute__((optimize("-O3")))
ll read()
{
ll x=0,f=1;
char ch=getchar();
while (ch<'0' || '9'<ch)
{
if (ch=='-')f=-1;
ch=getchar();
}
while ('0'<=ch && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
__attribute__((optimize("-O3")))
ll getfa(ll x)
{
return !fa[x]?x:fa[x]=getfa(fa[x]);
}
__attribute__((optimize("-O3")))
void link(ll x,ll y,ll z)
{
next[++tot]=last[x];
last[x]=tot;
tov[tot]=y;
len[tot]=z;
}
__attribute__((optimize("-O3")))
ll pow(ll x,ll y)
{
ll z=1;
while (y)
{
if (y&1)z=z*x%mod;
x=x*x%mod,y/=2;
}
return z;
}
__attribute__((optimize("-O3")))
void dfs(ll x,ll y)
{
if (a[x]%2==1)f[x]++;
for (register ll i=last[x];i;i=next[i])
if (tov[i]!=y)
{
dfs(tov[i],x);
if (f[tov[i]]%2==1)(ans+=pow(2,len[i]))%=mod;
f[x]+=f[tov[i]];
}
}
__attribute__((optimize("-O3")))
int main()
{
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
n=read(),m=read();
fo(i,1,m)
{
(ans+=pow(2,i))%=mod;
int x=read(),y=read();
a[x]++,a[y]++;
if (getfa(x)!=getfa(y))
{
fa[getfa(x)]=getfa(y);
link(x,y,i),link(y,x,i);
}
}
dfs(1,0);
printf("%lld\n",ans);
return 0;
}