两个给点染色的问题-树上染色与图上染色

两个给点染色的问题

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

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\n", (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\n", ans);
    return 0;
}

转载于:https://www.cnblogs.com/NeilThang/p/9397747.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我可以回答这个问题。红黑树是一种自平衡二叉查找树,它的节有红色和黑色两种颜色,通过一些规则来保证树的平衡性和查找效率。在 C 语言中,可以通过定义结构体来表示节,使用指针来进行节的插入、删除和查找操作。具体实现可以参考相关的算法书籍或者网上的教程。 ### 回答2: 红黑树是一种自平衡的二叉查找树,在C语言中可以使用指针和结构体来实现。 首先,需要定义红黑树的节结构体,包括键值、颜色、左右子节等信息。可以定义如下: ``` typedef struct Node { int key; // 节键值 char color; // 节颜色(红或黑) struct Node *parent; // 父节指针 struct Node *left; // 左子节指针 struct Node *right; // 右子节指针 } RBNode; ``` 然后,需要定义红黑树结构体,包括根节等信息。可以定义如下: ``` typedef struct RBTree { RBNode *root; // 根节指针 } RBTree; ``` 接下来,可以实现一些红黑树常用的操作函数,比如插入、删除、查找等。以下是红黑树插入操作的示例代码: ```c void insert(RBTree *tree, int key) { // 创建新节 RBNode *newNode = createNode(key); // 在合适的位置插入节 // 若树为空,将新节设置为根节 if (tree->root == NULL) { newNode->color = 'B'; // 根节为黑色 tree->root = newNode; } else { RBNode *current = tree->root; RBNode *parent = NULL; // 在树中查找合适的插入位置 while (current != NULL) { parent = current; if (newNode->key < current->key) current = current->left; else current = current->right; } // 更新父节和新节的关系 if (newNode->key < parent->key) parent->left = newNode; else parent->right = newNode; newNode->parent = parent; // 对树进行旋转和着色操作,使其符合红黑树的性质 fixupAfterInsert(tree, newNode); } } ``` 以上只是红黑树的一个简化实现,完整的红黑树还需要实现删除、查找等操作,并且需保证树的平衡。在实现过程中需要要注意红黑树的性质,如节颜色、双重黑色节、旋转等操作。 通过以上步骤,我们可以通过C语言来实现一个简单的红黑树。 ### 回答3: 红黑树是一种自平衡的二叉搜索树,简单理解就是在普通的二叉搜索树的基础上通过染色来保持树的平衡。 要用C语言实现红黑树,首先需要定义红黑树的数据结构。每个节应包括键值、颜色(红或黑)、父节指针、左子节指针和右子节指针等基本成员。 操作包括插入、删除和搜索等。插入操作分为插入和修正两个过程。在插入过程中,树要保持二叉搜索树的性质,即保持左子节小于父节,右子节大于父节。插入过程的修正步骤涉及旋转和变色操作,以保持红黑树的平衡。 删除操作也包括删除和修正两个过程。删除节后,为了保持红黑树的平衡,需要根据被删除节的颜色和位置选择不同的修正方法。 搜索操作则是按照二叉搜索树的性质,比较目标节的键值和当前节的键值大小,递归地在左子树或右子树中搜索。 除了上述的基本操作外,还可以实现前序遍历、中序遍历和后序遍历等方法,以及其他辅助方法,如计算树的高度、判断两棵树是否相等等。 总之,用C语言实现红黑树的关键是要理解红黑树的特性,以及如何在插入和删除操作过程中进行修正,以保持树的平衡。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值