#10 //I [HNOI/AHOI2018]毒瘤

题解:

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[15];
const int n2=1e7;
int head[N],l2,l,v[N],n,m,hash[n2];
ll dp[N][2],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]=1;
  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]=1;
          ff[u%2?u+1:u-1]=1;
        }
      } else dfs(v,u%2?u+1:u-1);
    }
    u=a[u].a;
  }
}
inline void dfs3(rg int x,rg int y)
{
  rg int u=head[x];
  dp[x][0]=1; dp[x][1]=1;
  if (v[x]==1) dp[x][0]=0;
  if (v[x]==-1) dp[x][1]=0;
  while (u)
  {
    rg int v=a[u].b;
    if (u!=y&&!ff[u])
    {
      dfs3(v,u%2?u+1:u-1);
      dp[x][1]*=dp[v][0];
      dp[x][1]%=mo;
      dp[x][0]*=(dp[v][0]+dp[v][1]);
      dp[x][0]%=mo;
    }
    u=a[u].a;
  }
}
const int mo1=9e6+7;
inline void dfs2(rg int now)
{
  if (now==0)
  {
    memset(dp,0,sizeof(dp));
    dfs3(1,0);
    ans+=dp[1][0]+dp[1][1];
    ans%=mo;
    return;
  }
  rg int x=ts[now].a,y=ts[now].b;
  rg int tmp1=v[x],tmp2=v[y];
  if (v[x]!=1&&v[y]!=-1)
  {
    v[x]=-1; v[y]=1; dfs2(now-1); v[x]=tmp1; v[y]=tmp2;
  }
  if (v[y]!=1)
  {
    v[y]=-1; dfs2(now-1); 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=1;i<=m;i++)
  {
    cin>>x>>y;
    arr(x,y); arr(y,x);
  }
  dfs(1,0);
  dfs2(l2);
  cout<<ans<<endl;
  return 0;
}

 

posted @ 2018-04-26 22:40  尹吴潇  阅读(380)  评论(0编辑  收藏  举报