1. 程式人生 > >#10 //I [HNOI/AHOI2018]毒瘤

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

div 我們 ++ ack cin 一個點 mem 簡單的 dfs

題解:

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; }

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