码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-02-27 00:49:31      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:tor   class   present   traints   turn   HERE   print   之间   represent   

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=\bigcup_1^{m} A_i\)

根据容斥定理:

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

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

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

因为\(n\leq 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\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.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\n", ans);
    return 0;
}

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

标签:tor   class   present   traints   turn   HERE   print   之间   represent   

原文地址:https://www.cnblogs.com/qieqiemin/p/12370064.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!