题解:

80分做法还是听简单的

对于非树边枚举一下端点状态

然而我也不知道为什么就多t了一个点

具体实现上

最暴力的是3^n次 但是我们可以发现对于i不取,j取 i不取,j不取是可以等效成i不取,j没有限制,这样是2^n

或者直接容斥一下搞i取j取 这样C(n,1)+C(n,2)...=2^n一样的吧

100pts应该是虚树处理一下系数吧

代码:

#include <bits/stdc++.h>
using namespace std;
#define N 300000
#define rg register
#define mo 998244353
#define ll long long
struct re{
int a,b;
}a[N],ts[];
const int n2=1e7;
int head[N],l2,l,v[N],n,m,hash[n2];
ll dp[N][],ans;
bool f[N],ff[N];
inline void arr(int x,int y)
{
a[++l].a=head[x];
a[l].b=y;
head[x]=l;
}
inline void dfs(int x,int y)
{
rg int u=head[x];
f[x]=;
while (u)
{
rg int v=a[u].b;
if (u!=y)
{
if (f[v])
{
if (!ff[u])
{
ts[++l2].a=a[u].b;
ts[l2].b=x;
ff[u]=;
ff[u%?u+:u-]=;
}
} else dfs(v,u%?u+:u-);
}
u=a[u].a;
}
}
inline void dfs3(rg int x,rg int y)
{
rg int u=head[x];
dp[x][]=; dp[x][]=;
if (v[x]==) dp[x][]=;
if (v[x]==-) dp[x][]=;
while (u)
{
rg int v=a[u].b;
if (u!=y&&!ff[u])
{
dfs3(v,u%?u+:u-);
dp[x][]*=dp[v][];
dp[x][]%=mo;
dp[x][]*=(dp[v][]+dp[v][]);
dp[x][]%=mo;
}
u=a[u].a;
}
}
const int mo1=9e6+;
inline void dfs2(rg int now)
{
if (now==)
{
memset(dp,,sizeof(dp));
dfs3(,);
ans+=dp[][]+dp[][];
ans%=mo;
return;
}
rg int x=ts[now].a,y=ts[now].b;
rg int tmp1=v[x],tmp2=v[y];
if (v[x]!=&&v[y]!=-)
{
v[x]=-; v[y]=; dfs2(now-); v[x]=tmp1; v[y]=tmp2;
}
if (v[y]!=)
{
v[y]=-; dfs2(now-); v[y]=tmp2;
}
}
int main()
{
freopen("noi.in","r",stdin);
freopen("noi.out","w",stdout);
std::ios::sync_with_stdio(false);
cin>>n>>m;
int x,y;
for (rg int i=;i<=m;i++)
{
cin>>x>>y;
arr(x,y); arr(y,x);
}
dfs(,);
dfs2(l2);
cout<<ans<<endl;
return ;
}
04-18 09:08