zoukankan      html  css  js  c++  java
  • 两个给点染色的问题-树上染色与图上染色

    两个给点染色的问题

    写在前面:最近做了两个染色问题,都是问染色方案数,但是解题方法完全不同。

    Coloring Tree @牛客网暑期ACM多校训练营(第三场)G

    PROBLEM1 【bfs】【树上染色问题】

    题目描述

    Christmas is coming! Eddy has received a Christmas tree as gift. Not surprisingly, the tree consists of N vertices and N-1 edges and magically remains connected. Currently, all the vertex of the tree is uncolored. Eddy wants to color each vertex into one of K colors. However, there are too many way to color the tree(i.e. KN ways). Eddy doesn't want the result of coloring being too boring. Thus, he defines the colorness of a tree as follow:
    The colorness of a tree is the minimum distance between two vertex colored in the same color.
    Now, Eddy is wondering how many way to color the tree such that the colorness of the tree will be D.

    输入描述:

    The first line of input contains three space-separated integer N, K, D indicating the number of vertices, number of colors, and the required colorness.
    For each following N-1 lines, each contains two space-separated positive integer ui, vi indicating that there's an edge between ui and vi.
    1 ≤ K < N ≤ 5000
    1 ≤ D ≤ N
    1 ≤ ui < vi ≤ N
    It's guaranteed that the given input is a tree.

    输出描述:

    Output one line contains an integer indicating the number of way module 1000000007(109+7) to color the tree resulting in colorness being D.

    示例1

    输入
    2 1 1
    1 2
    输出
    1

    示例2

    输入
    4 3 2
    1 2
    2 3
    3 4
    输出
    18

    示例3

    输入
    4 3 2
    1 2
    1 3
    1 4
    输出
    24

    MEANING1

    一个n个结点的树,用k种颜色给树上的结点染色,要求相同染色结点距离恰好为d。问染色方案数。

    SOLUTION1

    构建一个函数f(d),表示相同颜色的点的距离至少为d时,染色的方案数。
    那么答案就等于f(d)-f(d+1)。
    至于求解f(d),可以用bfs的方法,确定染色顺序。对于当前点再做一次bfs,统计与他距离不超过d的已经染色的点的数量m,这些点一定是不同色的,所以当前点可选颜色数为max(k-m,0)。
    将每个点的方案数相乘就是总方案数。
    时间复杂度o((N^2))。

    CODE1

    #define IN_PC() freopen("C:\Users\hz\Desktop\in.txt","r",stdin)
    #define IN_LB() freopen("C:\Users\acm2018\Desktop\in.txt","r",stdin)
    #define OUT_PC() freopen("C:\Users\hz\Desktop\out.txt","w",stdout)
    #define OUT_LB() freopen("C:\Users\acm2018\Desktop\out.txt","w",stdout)
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 5005;
    //const int INF = 0x3f3f3f3f;
    const ll MOD = 1e9 + 7;
    
    int numV, numC, rd;
    
    struct edge {
        int v, nex;
    } ed[MAXN * 2];
    
    int cnt, head[MAXN];
    
    void addedge(int u, int v) {
        cnt++;
        ed[cnt].v = v;
        ed[cnt].nex = head[u];
        head[u] = cnt;
    }
    
    int vis[MAXN],vis2[MAXN];
    
    struct node {
        int name, step;
    };
    
    int bfs(int cur, int d) {
        memset(vis2, 0, sizeof vis2);
        int cnt = 0;
        queue<node> q2;
        q2.push({cur, 0});
        vis2[cur] = 1;
        while(!q2.empty()) {
            int u = q2.front().name, step = q2.front().step;
            q2.pop();
            for(int i = head[u]; i; i = ed[i].nex) {
                int v = ed[i].v;
                if(vis[v] && step + 1 < d && !vis2[v]) {
                    q2.push({v, step + 1});
                    vis2[v] = 1;
                    cnt++;
                }
            }
        }
        return cnt;
    }
    
    ll fun(int d) {
        memset(vis,0,sizeof vis);
        ll res = 1;
        queue<int> q1;
        q1.push(1);
        while(!q1.empty()) {
            int cur = q1.front();
            vis[cur] = 1;
            q1.pop();
            res = res * (numC - bfs(cur, d)) % MOD;
            for(int i = head[cur]; i; i = ed[i].nex) {
                int v = ed[i].v;
                if(!vis[v])
                    q1.push(v);
            }
        }
        return res;
    }
    
    int main() {
    //    IN_PC();
        scanf("%d%d%d", &numV, &numC, &rd);
        for(int i = 0; i < numV - 1; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            addedge(u, v);
            addedge(v, u);
        }
        printf("%lld
    ", (fun(rd) - fun(rd + 1) + MOD) % MOD);
        return 0;
    }
    
    

    Coloring Dominoes @ABC071&ARC081

    PROBLEM2 【图上染色问题】

    题目描述

    We have a board with a 2×N grid. Snuke covered the board with N dominoes without overlaps. Here, a domino can cover a 1×2 or 2×1 square.
    Then, Snuke decided to paint these dominoes using three colors: red, cyan and green. Two dominoes that are adjacent by side should be painted by different colors. Here, it is not always necessary to use all three colors.
    Find the number of such ways to paint the dominoes, modulo 1000000007.
    The arrangement of the dominoes is given to you as two strings S1 and S2 in the following manner:
    Each domino is represented by a different English letter (lowercase or uppercase).
    The j-th character in Si represents the domino that occupies the square at the i-th row from the top and j-th column from the left.
    Constraints
    1≤N≤52
    |S1|=|S2|=N
    S1 and S2 consist of lowercase and uppercase English letters.
    S1 and S2 represent a valid arrangement of dominoes.

    输入

    Input is given from Standard Input in the following format:
    N
    S1
    S2

    输出

    Print the number of such ways to paint the dominoes, modulo 1000000007.

    样例输入

    3
    aab
    ccb

    样例输出

    6

    MEANING2

    2N的棋盘用1x2和2x1的色块覆盖,相邻色块不重复 。问覆盖方法数

    SOLUTION2

    与树上染色不同,图上染色不能bfs,因为对于当前点,它相邻的已经染色的点可能不同色,也可能同色,不同情况当前点可选的颜色是不同的。

    CODE2

    #define IN_PC() freopen("C:\Users\hz\Desktop\in.txt","r",stdin)
    #define IN_LB() freopen("C:\Users\acm2018\Desktop\in.txt","r",stdin)
    #define OUT_PC() freopen("C:\Users\hz\Desktop\out.txt","w",stdout)
    #define OUT_LB() freopen("C:\Users\acm2018\Desktop\out.txt","w",stdout)
    #include <bits/stdc++.h>
     
    using namespace std;
    typedef long long ll;
    const int MAXN = 53;
    const ll MOD = 1000000007;
    char mapp[2][MAXN];
    
    int main() {
    //    IN_PC();
        int n;
        scanf("%d", &n);
        for(int i = 0; i < 2; i++)
            scanf("%s", mapp[i]);
        ll ans = 1;
        for(int i = 0; i < n; i++) {
            if(mapp[0][i] != mapp[1][i]) {
                if(i == 0)ans *= 6;
                else if(mapp[0][i-1]==mapp[1][i-1])ans = (ans * 2) % MOD;
                else ans = (ans * 3) % MOD;
                i ++;
            } else {
                if(i == 0)ans *= 3;
                else if(mapp[0][i-1]==mapp[1][i-1])ans = (ans * 2) % MOD;
                else ans = ans * 1 % MOD;
            }
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    一个总成本花费100W的失败项目的小小反省
    从绝望中寻找希望
    一个合格程序员该做的事情——你做好了吗?
    Go to 北京!
    深入浅出Oracle分析函数
    最适合web开发人员使用的速查表
    采用axis2c进行webservice发布的流程4在生成的代码中添加事务处理逻辑
    采用axis2c进行webservice发布的流程1
    rhel6.0及centos6.0 忘记root密码解决办法
    采用axis2c进行webservice发布的流程3通过wsdl文件,自动生成C的服务端代码
  • 原文地址:https://www.cnblogs.com/NeilThang/p/9397747.html
Copyright © 2011-2022 走看看