题解 洛谷 P4221 【[WC2018]州区划分】

一个州不合法为其内部有欧拉回路,即图连通且每个点度数都为偶数。

\(n\) 很小,考虑用状压 \(DP\) 解决本题,设 \(f_S\) 为集合 \(S\) 的答案,$ g_S $ 为集合 \(S\)\(w\) 和的 \(p\) 次方。

得转移方程为:

\[ f_S= \frac{1}{g_S} \sum_{ T \subset S } f_T g_{S-T} \]

其中 \(S,T,S-T\) 都为合法的集合。直接枚举子集转移是 \(O(n^3)\),复杂度无法接受,观察式子后,发现用子集卷积优化即可,

\(code:\)

#include
#define maxn 25
#define maxm 510
#define maxs 2400010
#define p 998244353
#define lowbit(x) (x&(-x))
using namespace std;
typedef long long ll;
template inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
ll n,m,k,all;
ll v[maxn],fa[maxn],d[maxn];
ll f[maxn][maxs],g[maxn][maxs],sum[maxs],inv[maxs],cnt[maxs];
struct edge
{
    int x,y;
}e[maxm];
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void FWT(ll *a,int type)
{
    for(int len=1;len>=1;
    }
    return v;
}
bool check(int s)
{
    if(cnt[s]<=1) return false;
    memset(d,0,sizeof(d));
    for(int i=1;i<=n;++i) fa[i]=i;
    int num=0;
    for(int i=1;i<=m;++i)
    {
        int x=e[i].x,y=e[i].y;
        if(!(s&(1<<(x-1)))||!(s&(1<<(y-1)))) continue;
        if(find(x)!=find(y)) fa[find(x)]=find(y),num++;
        d[x]++,d[y]++;
    }
    if(num!=cnt[s]-1) return true;
    for(int i=1;i<=n;++i)
        if(d[i]&1)
            return true;
    return false;
}
int main()
{
    read(n),read(m),read(k),all=1<

你可能感兴趣的:(题解 洛谷 P4221 【[WC2018]州区划分】)