zoukankan      html  css  js  c++  java
  • #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;
    }
  • 相关阅读:
    AcWing242一个简单的整数问题1(差分+树状数组)
    AcWing241楼兰图腾(树状数组)
    AcWing802区间和
    离散化
    AcWing1250格子游戏(并查集)
    vijos难解的问题(LIS最长上升子序列)
    动态规划dp——LIS(最长上升子序列)、LCS(最长公共子序列)
    约数、素数、gcd(最大公约数)、lcm(最小公倍数)
    vijos拓扑编号(逆向拓扑排序+优先队列)
    洛谷P1137旅行计划(拓扑排序+简单dp)
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8955432.html
Copyright © 2011-2022 走看看