• hdu 5977 Garden of Eden(点分治+状压)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5977

    题解:这题一看就知道是状压dp然后看了一下很像是点分治(有点明显)然后就是简单的点分治+状压dp,这里只要稍微改一下模版就行了。还有注意一下这里的cau状态枚举然后就没什么了

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    const int M = 5e4 + 10;
    struct Edge {
        int v , next;
    }edge[M << 1];
    int head[M] , e , Size , root , n , k , a[M] , ssr;
    ll ans;
    bool vis[M];
    void init() {
        memset(head , -1 , sizeof(head));
        memset(vis , false , sizeof(vis));
        ans = 0;
        e = 0;
        ssr = ((1 << k) - 1);
    }
    void add(int u , int v) {
        edge[e].v = v;
        edge[e].next = head[u];
        head[u] = e++;
    }
    int size[M] , mx[M];
    ll Hash[1025];
    void dfs_size(int u , int pre) {
        size[u] = 1;
        mx[u] = 0;
        for(int i = head[u] ; i != -1 ; i = edge[i].next) {
            int v = edge[i].v;
            if(v == pre || vis[v]) continue;
            dfs_size(v , u);
            size[u] += size[v];
            mx[u] = max(mx[u] , size[v]);
        }
    }
    void dfs_root(int r , int u , int pre) {
        mx[u] = max(mx[u] , size[r] - size[u]);
        if(mx[u] < Size) Size = mx[u] , root = u;
        for(int i = head[u] ; i != -1 ; i = edge[i].next) {
            int v = edge[i].v;
            if(v == pre || vis[v]) continue;
            dfs_root(r , v , u);
        }
    }
    void get_root(int u , int pre) {
        dfs_size(u , pre);
        dfs_root(u , u , pre);
    }
    int num , State[M];
    void find_state(int u , int pre , int state) {
        State[num++] = state;
        for(int i = head[u] ; i != -1 ; i = edge[i].next) {
            int v = edge[i].v;
            if(vis[v] || v == pre) continue;
            find_state(v , u , state | (1 << a[v]));
        }
    }
    ll cau(int u , int state) {
        num = 0;
        find_state(u , -1 , state);
        memset(Hash , 0 , sizeof(Hash));
        ll sum = 0;
        for(int i = 0 ; i < num ; i++) Hash[State[i]]++;
        for(int i = 0 ; i < num ; i++) {
            Hash[State[i]]--;
            sum += Hash[ssr];//这里由于是枚举时0枚举不到所以先加上ssr^0.
            for (int s0 = State[i]; s0; s0 = (s0 - 1) & State[i])
                sum += Hash[((1 << k) - 1) ^ s0];
            Hash[State[i]]++;
        }
        return sum;
    }
    void dfs(int u) {
        Size = n;
        get_root(u , -1);
        ans += cau(root , (1 << a[root]));
        vis[root] = true;
        int rt = root;
        for(int i = head[root] ; ~i ; i = edge[i].next) {
            int v = edge[i].v;
            if(vis[v]) continue;
            ans -= cau(v , (1 << a[rt]) | (1 << a[v]));
            dfs(v);
        }
    }
    int main() {
        while(scanf("%d%d" , &n , &k) != EOF) {
            init();
            for(int i = 1 ; i <= n ; i++) scanf("%d" , &a[i]) , a[i]--;
            for(int i = 0 ; i < n - 1 ; i++) {
                int u , v;
                scanf("%d%d" , &u , &v);
                add(u , v);
                add(v , u);
            }
            if (k == 1) {
                printf("%lld
    ", (ll)n * (ll)n);
                continue;
            }
            dfs(1);
            printf("%lld
    " , ans);
        }
        return 0;
    }
  • 相关阅读:
    HBase 操作
    HBase Java API 例子
    微信浏览器拖动出现黑色/白色背景、网址问题解决方案
    layui弹出层置顶弹出
    使用layui时,ajax执行后,重新渲染页面的方法
    宝塔更新
    js 播放音频文件 兼容火狐 谷歌浏览器
    SAP断点
    error_log 用法
    SE开头的事务代码
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/7745410.html
Copyright © 2020-2023  润新知