首先,我们需要给一个连通块找到一个直观的合法判定解。

那么我们必须以一种直观的方式将边按照权值分开,这样才能直观地判定一个合法的组。

一个常见的方式是将边从小到大依次加入进来,那么在任意时刻图上存在的边和不存在的边就恰好被一个权值分开了。

那么我们可以很清晰地发现,一个联通块是合法的,当且仅当在上述流程的某个时刻这个连通块会形成一个团。

于是此时一个很暴力的做法就是预处理出所有合法的连通块,然后状压 \(dp\),但这样是指数级的,显然不可取。

看似这个问题已经难以优化了,但你会发现上面这个依次加边的模型非常类似于 \(\rm Kruskal\) 重构树,那么这个 \(dp\) 可不可以在重构树上被优化呢?

那么你会发现上面的这个团只可能是 \(\rm Kruskal\) 重构树上的一颗子树或一个单点,同时这些团也可以在 \(\rm Kruskal\) 的流程中求出。

于是问题就转化为给定一棵树,你需要把这颗树划分成 \(k\) 个联通块,每个可划分的联通块都是给定的的方案。

不难发现这个东西可以直接树形背包 \(O(n ^ 2)\) 解决。

#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define Next(i, u) for (int i = h[u]; i; i = e[i].next)
const int N = 3000 + 5;
const int M = 1500 + 5;
const int Mod = 998244353;
struct edge { int v, next;} e[N << 1];
int n, tot, cnt, d[N], h[N], sz[N], fa[N], x[M * M], y[M * M], a[M][M], dp[N][M];
int read() {
char c; int x = 0, f = 1;
c = getchar();
while (c > '9' || c < '0') { if(c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int Inc(int a, int b) { return (a += b) >= Mod ? a - Mod : a;}
int Mul(int a, int b) { return 1ll * a * b % Mod;}
int find(int x) { return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);}
void add(int u, int v) {
e[++tot].v = v, e[tot].next = h[u], h[u] = tot;
e[++tot].v = u, e[tot].next = h[v], h[v] = tot;
}
void dfs(int u, int fa) {
int a = 0, b = 0;
Next(i, u) {
int v = e[i].v; if(v == fa) continue;
dfs(v, u); if(!a) a = v; else b = v;
}
rep(i, 1, sz[a]) rep(j, 1, sz[b]) dp[u][i + j] = Inc(dp[u][i + j], Mul(dp[a][i], dp[b][j]));
if(d[u] == sz[u] * (sz[u] - 1) / 2) dp[u][1] = 1;
}
int main() {
n = cnt = read();
rep(i, 1, n) rep(j, 1, n) a[i][j] = read(), x[a[i][j]] = i, y[a[i][j]] = j;
rep(i, 1, 2 * n) fa[i] = i, sz[i] = (i <= n);
rep(i, 1, n * (n - 1) / 2) {
int Fx = find(x[i]), Fy = find(y[i]);
if(Fx != Fy) {
d[++cnt] = d[Fx] + d[Fy] + 1, sz[cnt] = sz[Fx] + sz[Fy];
fa[Fx] = fa[Fy] = cnt, add(cnt, Fx), add(cnt, Fy);
}
else ++d[Fx];
}
dfs(cnt, 0);
rep(i, 1, n) printf("%d ", dp[cnt][i]);
return 0;
}

值得一提的是,当我们的做法与某个算法流程本质相同时,可以尝试在这个算法的基础上对我们的做法进行优化。

CF1408G Clusterization Counting的更多相关文章

  1. CodeForces 1408G Clusterization Counting

    题意 给定 \(n\) 个点的无向带权完全图,边权为 \(1\sim\frac{n(n-1)}{2}\).对于满足 \(1\leq k\leq n\) 的每个 \(k\) 求出将原图划分成 \(k\) ...

  2. Solution -「CF 1480G」Clusterization Counting

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 阶完全图,边权为 \(1\sim\frac{n(n-1)}2\) 的排列.称一种将点集划分为 \(k\) ...

  3. 萌新笔记——Cardinality Estimation算法学习(二)(Linear Counting算法、最大似然估计(MLE))

    在上篇,我了解了基数的基本概念,现在进入Linear Counting算法的学习. 理解颇浅,还请大神指点! http://blog.codinglabs.org/articles/algorithm ...

  4. POJ_2386 Lake Counting (dfs 错了一个负号找了一上午)

    来之不易的2017第一发ac http://poj.org/problem?id=2386 Lake Counting Time Limit: 1000MS   Memory Limit: 65536 ...

  5. ZOJ3944 People Counting ZOJ3939 The Lucky Week (模拟)

    ZOJ3944 People Counting ZOJ3939 The Lucky Week 1.PeopleConting 题意:照片上有很多个人,用矩阵里的字符表示.一个人如下: .O. /|\ ...

  6. find out the neighbouring max D_value by counting sort in stack

    #include <stdio.h> #include <malloc.h> #define MAX_STACK 10 ; // define the node of stac ...

  7. 1004. Counting Leaves (30)

    1004. Counting Leaves (30)   A family hierarchy is usually presented by a pedigree tree. Your job is ...

  8. 6.Counting Point Mutations

    Problem Figure 2. The Hamming distance between these two strings is 7. Mismatched symbols are colore ...

  9. 1.Counting DNA Nucleotides

    Problem A string is simply an ordered collection of symbols selected from some alphabet and formed i ...

随机推荐

  1. 【stm32】基于hal库使用野火指南者esp8266 WIFI模块进行TCP传输

    UART.c #include "stm32f1xx_it.h" #include "LED.h" #include "UART.h" #i ...

  2. 标准基座获取定位可以获取address城市,自定义基座获取不到address

    正常的返回应该 { "type": "WGS84", "altitude": 0, "latitude": 31.830 ...

  3. 云南农职《JavaScript交互式网页设计》 综合机试试卷①——实现购物车的结算

    一.语言和环境 实现语言:javascript.html.css. 开发环境:HBuilder. 二.题目2(100分) 1.功能需求: 马上过节了,电商网站要进行促销活动,需要实现该商城购物车的商品 ...

  4. 【】JSON介绍

    0.说明 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写. 同时也易于机器解析和生成. 它是基于JavaScript Programm ...

  5. Kafka基础教程(一):认识Kafka

    Kafka是Apache下的一个子项目,是一个高性能跨语言分布式发布/订阅消息队列系统,吞吐速率非常快,可以作为Hadoop的日志收集.Kafka是一个完全的分布式系统,这一点依赖于Zookeeper ...

  6. 接口测试 再也不必来回切换,发现一个接口测试软件,可以替代 Swagger+Mock+Jmeter+Postman

    ​ 前言 日常测试过程中,常常需要多种工具来接力完成自己的接口测试任务. 比如说, 使用swagger查看接口文档, 使用mock编造接口数据对前端页面做测试 使用postman测试后端接口, 用Jm ...

  7. Flink sql 之 两阶段聚合与 TwoStageOptimizedAggregateRule(源码分析)

    本文源码基于flink1.14 上一篇文章分析了<flink的minibatch微批处理>的源码 乘热打铁分析一下两阶段聚合的源码,因为使用两阶段要先开启minibatch,至于为什么后面 ...

  8. 将ymal文件内容转换成字典格式

    yaml文件内容如图: 转换代码如下: import yaml def init_yaml(): with open(r"..\config.yaml", 'r', encodin ...

  9. git branch --set-upstream-to 本地关联远程分支

    最近使用git pull的时候多次碰见下面的情况: There is no tracking information for the current branch. Please specify wh ...

  10. spring boot 启动读取的配置文件优先级

    1.优先级从高到低 1.  file:/config/ 2. file:/ 3. classpath:/config/ 4. classpath:/ 所有位置的application.properti ...