CF704C Black Widow

因为一个 (x_i) 不会出现超过两次,因此将有相同 (x_i) 的表达式之间连边,得到的图为若干链和环。

(f_{i,0/1,0/1,0/1}) 为考虑了链或环的前 (i) 个点,第一个点的状态,上一个变量的状态,现在的异或和状态的方案数,分类讨论来转移,最后将所有连通块的信息合并。

要注意处理自环和孤立点的情况。

#include<bits/stdc++.h>
#define maxn 200010
#define p 1000000007
using namespace std;
typedef long long ll;
template<typename T> 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;
}
int n,m,tot;
int bel[maxn],deg[maxn];
ll f[maxn][2][2][2],g[maxn][2],h[maxn][2];
bool vis[maxn];
struct node
{
    int k;
    int v[2];
}a[maxn];
struct edge
{
    int to,nxt,v;
}e[maxn];
int head[maxn],edge_cnt=1;
void add(int from,int to,int val)
{
    e[++edge_cnt]={to,head[from],val},head[from]=edge_cnt;
    e[++edge_cnt]={from,head[to],val},head[to]=edge_cnt;
    deg[from]++,deg[to]++;
}
void dfs(int x,int link)
{
    if(!link)
    {
        f[x][0][0][0]=1;
        f[x][1][1][0]=a[x].k==2;
    }
    vis[x]=true;
    int cnt=0;
    for(int i=head[x];i;i=e[i].nxt)
    {
        int y=e[i].to;
        if(cnt==1) break;
        if(i==link||(i^1)==link) continue;
        cnt++;
        bool flag;
        for(int j=0;j<a[x].k;++j)
            for(int k=0;k<a[y].k;++k)
                if(abs(a[x].v[j])==abs(a[y].v[k])&&abs(a[x].v[j])==e[i].v)
                    flag=(a[x].v[j]==-a[y].v[k]);
        if(vis[y])
        {
            if(!flag)
            {
                g[tot][0]=(f[x][0][0][0]+f[x][0][1][1]+f[x][1][0][1]+f[x][1][1][1])%p;
                g[tot][1]=(f[x][0][1][0]+f[x][0][0][1]+f[x][1][0][0]+f[x][1][1][0])%p;
            }
            else
            {
                g[tot][0]=(f[x][0][1][1]+f[x][1][0][0]+f[x][0][0][1]+f[x][1][1][1])%p;
                g[tot][1]=(f[x][0][0][0]+f[x][0][1][0]+f[x][1][1][0]+f[x][1][0][1])%p;
            }
        }
        else
        {
            if(!flag)
            {
                for(int j=0;j<=1;++j)
                {
                    f[y][j][1][1]=(f[y][j][1][1]+f[x][j][0][0])%p;
                    f[y][j][0][0]=(f[y][j][0][0]+f[x][j][0][0])%p;
                    f[y][j][1][1]=(f[y][j][1][1]+f[x][j][1][0])%p;
                    f[y][j][0][1]=(f[y][j][0][1]+f[x][j][1][0])%p;
                    f[y][j][1][0]=(f[y][j][1][0]+f[x][j][0][1])%p;
                    f[y][j][0][1]=(f[y][j][0][1]+f[x][j][0][1])%p;
                    f[y][j][1][0]=(f[y][j][1][0]+f[x][j][1][1])%p;
                    f[y][j][0][0]=(f[y][j][0][0]+f[x][j][1][1])%p;
                }
            }
            else
            {
                for(int j=0;j<=1;++j)
                {
                    f[y][j][0][1]=(f[y][j][0][1]+f[x][j][0][0])%p;
                    f[y][j][1][0]=(f[y][j][1][0]+f[x][j][0][0])%p;
                    f[y][j][1][1]=(f[y][j][1][1]+f[x][j][1][0])%p;
                    f[y][j][0][1]=(f[y][j][0][1]+f[x][j][1][0])%p;
                    f[y][j][1][1]=(f[y][j][1][1]+f[x][j][0][1])%p;
                    f[y][j][0][0]=(f[y][j][0][0]+f[x][j][0][1])%p;
                    f[y][j][1][0]=(f[y][j][1][0]+f[x][j][1][1])%p;
                    f[y][j][0][0]=(f[y][j][0][0]+f[x][j][1][1])%p;
                }
            }
            dfs(y,i);
        }
    }
    if(!cnt)
    {
        if(a[x].k==1)
        {
            g[tot][0]=(f[x][0][1][1]+f[x][0][0][0]+f[x][1][0][0]+f[x][1][1][1])%p;
            g[tot][1]=(f[x][0][0][1]+f[x][0][1][0]+f[x][1][0][1]+f[x][1][1][0])%p;
        }
        else
        {
            g[tot][0]=(f[x][0][0][1]+f[x][0][1][1]+f[x][1][0][1]+f[x][1][1][1]+f[x][0][0][0]+f[x][0][1][1]+f[x][1][0][0]+f[x][1][1][1])%p;
            g[tot][1]=(f[x][0][0][0]+f[x][0][1][0]+f[x][1][0][0]+f[x][1][1][0]+f[x][0][0][1]+f[x][0][1][0]+f[x][1][0][1]+f[x][1][1][0])%p;
        }
    }
}
int main()
{
    read(n),read(m);
    for(int i=1;i<=n;++i)
    {
        read(a[i].k);
        for(int j=0;j<a[i].k;++j)
        {
            read(a[i].v[j]);
            int id=abs(a[i].v[j]);
            if(!bel[id]) bel[id]=i;
            else
            {
                if(i!=bel[id]) add(i,bel[id],id);
                else
                {
                    vis[i]=true,tot++;
                    if(a[i].v[0]==a[i].v[1]) g[tot][0]=g[tot][1]=1;
                    else g[tot][1]=2;
                }
                bel[id]=-1;
            }
        }
    }
    for(int i=1;i<=m;++i)
    {
        if(a[bel[i]].k!=1) continue;
        vis[bel[i]]=true,tot++,g[tot][0]=g[tot][1]=1;
    }
    for(int i=1;i<=n;++i)
        if(!vis[i]&&deg[i]==1)
            tot++,dfs(i,0);
    for(int i=1;i<=n;++i)
        if(!vis[i])
            tot++,dfs(i,0);
    h[0][0]=1;
    for(int i=1;i<=tot;++i)
    {
        h[i][0]=(h[i-1][0]*g[i][0]%p+h[i-1][1]*g[i][1]%p)%p;
        h[i][1]=(h[i-1][0]*g[i][1]%p+h[i-1][1]*g[i][0]%p)%p;
    }
    for(int i=1;i<=m;++i)
    	if(!bel[i])
    		h[tot][1]=h[tot][1]*2%p;
    printf("%lld",h[tot][1]);
    return 0;
}
原文地址:https://www.cnblogs.com/lhm-/p/13871117.html