AtCoder Beginner Contest 152 - F - Tree and Constraints (容斥定理+树上路径的性质)

Posted qieqiemin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 152 - F - Tree and Constraints (容斥定理+树上路径的性质)相关的知识,希望对你有一定的参考价值。

AtCoder Beginner Contest 152 - F - Tree and Constraints (容斥定理+树上路径的性质)

We have a tree with NN vertices numbered 11 to NN. The ii-th edge in this tree connects Vertex aiai and Vertex bibi.
Consider painting each of these edges white or black. There are 2N?12N?1 such ways to paint the edges. Among them, how many satisfy all of the following MM restrictions?

  • The ii-th (1≤i≤M)(1≤i≤M) restriction is represented by two integers uiui and vivi, which mean that the path connecting Vertex uiui and Vertex vivi must contain at least one edge painted black.

题意:

给定一个含有n个节点的树,每一条边可以给其染成黑色或者白色。

还有m个限制条件,每一个限制条件包括两个节点(u,v),限制为(u,v)节点之间的路径中必须包含至少一个涂成黑色的边。

问有多少种染色方法使其同时满足m个条件。

思路:

答案(ans=v1-v2)

(v1)代表所有染色方案,(v2)代表不满足条件的染色方案

我们知道(v1=2^{n-1})

那么问题就直接转换成了求(v2)

(A_i)代表不满足第i个限制条件的方案数,那么(v2)就等于(A_i)的并集,即(v2=igcup_1^{m} A_i)

根据容斥定理:

技术图片那么我们就可以直接枚举(m)个限制的所有集合来求出(v2)

那么问题来了,怎么求(A_i)呢?

(path_j)代表从根节点(无根树的话就假定一个根)到第(j)个节点经过了哪些边。

因为(nleq 50),所以(path_i)我们采用$long long $ 数据类型进行二进制状态压缩表示。

那么节点(x,y)之间的路径经历的边信息(info=path_x oplus path_y)(oplus) 是抑或符号。

那么对于枚举的每一个集合(i),把包含的所有限制的边信息(info)或起来后计算有多少个边,假设个数为(num)

那么这(num)个边染成白色时集合(i)才不满足条件。那么剩下(free=n-1-num)个边可以自由染色。

直接根据奇偶判断在容斥定理中公式的正负号即可。

代码:

int n;
int m;
std::vector<int> v[maxn];
ll path[maxn];
void dfs(int x, int pre, ll num)
{
    path[x] = num;
    for (auto y : v[x])
    {
        if (y == pre)
        {
            continue;
        }
        dfs(y, x, num | (1ll << y));
    }
}
ll info[maxn];

int main()
{
    //freopen("D:code	extinput.txt","r",stdin);
    //freopen("D:code	extoutput.txt","w",stdout);
    n = readint();
    repd(i, 1, n - 1)
    {
        int x = readint();
        int y = readint();
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dfs(1, 0, 0ll);
    m = readint();
    repd(i, 0, m - 1)
    {
        int x = readint();
        int y = readint();
        info[i] = (path[x] ^ path[y]);
    }
    int maxstate = (1 << m) - 1;
    ll ans = 0ll;
    repd(i, 0, maxstate)
    {
        ll num = 0ll;
        int cnt = 0;
        repd(j, 0, m - 1)
        {
            if (i & (1 << j)) {
                cnt++;
                num |= info[j];
            }
        }
        int free = n - 1 - __builtin_popcountll(num);
        ans += poww(2ll, free) * (cnt & 1 ? -1ll : 1ll);
    }
    printf("%lld
", ans);
    return 0;
}

以上是关于AtCoder Beginner Contest 152 - F - Tree and Constraints (容斥定理+树上路径的性质)的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242