CodeForces 1408G Clusterization Counting
题意
给定 \(n\) 个点的无向带权完全图,边权为 \(1\sim\frac{n(n-1)}{2}\)。对于满足 \(1\leq k\leq n\) 的每个 \(k\) 求出将原图划分成 \(k\) 个组的方案数,满足组间边的权大于组内边的权值,答案对 \(998244353\) 取模。
\(\texttt{Data Range:}1\leq n\leq 1500\)
题解
这个题蛮好的,只是我赛时没有想出来(甚至差点没有看懂题目),果然还是我太菜了/kk
首先从小到大把边加进来,然后可以发现一个结论:一个连通块是满足条件的当且仅当在加完某条边之后这个连通块是一个团。
这个时候可以直接用类似于 Kruskal 的方法:从小到大加边,并查集维护一下这个连通块的大小和边数,当加完某条边时候可以满足这个连通块是一个团的话就标记一下这个连通块是可以的。
这个时候好像是可以 DP 了,但是复杂度会爆炸。
考虑优化一下,在从小到大加边的过程中考虑 Kruskal 重构树。由于重构树新加的节点维护的是一个连通块,其叶子节点是连通块中所有的节点,所以可以对重构树进行 dfs,用一段区间表示一个连通块。
于是现在变成了有一些区间,要从中选出 \(k\) 个覆盖 \(1\sim n\) 的所有位置。把所有区间挂到右端点上,设 \(f_{i,j}\) 表示当前位置为 \(i\) 并且钦定当前最后一个区间右端点为 \(i\),选出了 \(j\) 个区间的答案,转移的时候枚举一下最后一个区间的左端点是什么就没了。
时间复杂度 \(O(n^2\log n)\),主要瓶颈在排序上。
代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=3e3+51,MOD=998244353;
struct EdgeForKruskal{
ll from,to,dist;
inline bool operator <(const EdgeForKruskal &rhs)const
{
return this->dist<rhs.dist;
}
};
EdgeForKruskal ed[MAXN*MAXN];
ll n,m,idx,u,v,itvc;
ll x[MAXN][MAXN],f[MAXN][MAXN],ffa[MAXN],sz[MAXN],edc[MAXN];
ll l[MAXN],r[MAXN],flg[MAXN];
vector<ll>g[MAXN],itv[MAXN];
inline ll read()
{
register ll num=0,neg=1;
register char ch=getchar();
while(!isdigit(ch)&&ch!='-')
{
ch=getchar();
}
if(ch=='-')
{
neg=-1;
ch=getchar();
}
while(isdigit(ch))
{
num=(num<<3)+(num<<1)+(ch-'0');
ch=getchar();
}
return num*neg;
}
inline ll find(ll x)
{
return ffa[x]==x?x:ffa[x]=find(ffa[x]);
}
inline void add(ll x)
{
if((++edc[x])==sz[x]*(sz[x]-1)/2)
{
flg[x]=1;
}
}
inline void dfs(ll x)
{
if(x<=n)
{
return (void)(l[x]=r[x]=++itvc);
}
l[x]=n+1;
for(register int to:g[x])
{
dfs(to),l[x]=min(l[x],l[to]);
}
r[x]=itvc,flg[x]?itv[r[x]].push_back(l[x]):(void)1;
}
int main()
{
n=read(),f[0][0]=1;
for(register int i=1;i<=n;i++)
{
for(register int j=1;j<=n;j++)
{
x[i][j]=read();
j>i?(void)(ed[++m]=(EdgeForKruskal){i,j,x[i][j]}):(void)1;
}
}
idx=n,sort(ed+1,ed+m+1);
for(register int i=1;i<=n;i++)
{
flg[i]=1,itv[i].push_back(i),ffa[i]=i,sz[i]=1,edc[i]=0;
}
for(register int i=1;i<=m;i++)
{
u=find(ed[i].from),v=find(ed[i].to);
if(u==v)
{
add(u);
}
else
{
g[++idx].push_back(u),g[idx].push_back(v);
ffa[u]=ffa[v]=ffa[idx]=idx;
sz[idx]=sz[u]+sz[v],edc[idx]=edc[u]+edc[v],add(idx);
}
}
dfs(idx);
for(register int i=1;i<=n;i++)
{
for(register int j=1;j<=n;j++)
{
for(register int k:itv[i])
{
f[i][j]=(f[i][j]+f[k-1][j-1])%MOD;
}
}
}
for(register int i=1;i<=n;i++)
{
printf("%d ",f[n][i]);
}
}
CodeForces 1408G Clusterization Counting的更多相关文章
- Codeforces 954H Path Counting 【DP计数】*
Codeforces 954H Path Counting LINK 题目大意:给你一棵n层的树,第i层的每个节点有a[i]个儿子节点,然后问你树上的简单路径中长度在1~n*2-2之间的每个有多少条 ...
- Codeforces 372 B. Counting Rectangles is Fun
$ >Codeforces \space 372 B. Counting Rectangles is Fun<$ 题目大意 : 给出一个 \(n \times m\) 的 \(01\) ...
- 【codeforces 335E】 Counting Skyscrapers
http://codeforces.com/problemset/problem/335/E (题目链接) 题意 懒得写了= = Solution 这题咋不上天= =. 参考题解:http://blo ...
- Codeforces 911D. Inversion Counting (数学、思维)
题目链接:Inversion Counting 题意: 定义数列{ai|i=1,2,...,n}的逆序对如下:对于所有的1≤j<i≤n,若ai<aj,则<i,j>为一个逆序对. ...
- Codeforces 954H Path Counting(DP)
题目链接 Path Counting 题意 给定一棵高度为$n$的树,给出每一层的每个点的儿子个数(某一层的所有点儿子个数相同). 令$f_{k}$为长度为$k$的路径条数,求$f_{1}, ...
- CodeForces - 990G GCD Counting
Discription You are given a tree consisting of nn vertices. A number is written on each vertex; the ...
- 【Codeforces 372A】Counting Kangaroos is Fun
[链接] 我是链接,点我呀:) [题意] 如果a[i]*2<=a[j]那么i袋鼠可以装进j袋鼠里面 每只袋鼠都只能装一只袋鼠 [题解] 假设最后的方案是(ai,bi) 这里(ai,bi)表示下标 ...
- CodeForces 372 A. Counting Kangaroos is Fun
题意,有n只袋鼠,没每只袋鼠有个袋子,大小为si,一个袋鼠可以进入另外一个袋鼠的袋子里面,当且仅当另一个袋鼠的袋子是他的二倍或二倍一上,然后中国袋鼠就是不可见的,不能出现多个袋鼠嵌套的情况.让你求最少 ...
- CF1408G Clusterization Counting
首先,我们需要给一个连通块找到一个直观的合法判定解. 那么我们必须以一种直观的方式将边按照权值分开,这样才能直观地判定一个合法的组. 一个常见的方式是将边从小到大依次加入进来,那么在任意时刻图上存在的 ...
随机推荐
- Spring Boot(二) :Redis 使用
Redis 介绍 Redis 是目前业界使用最广泛的内存数据存储.相比 Memcached,Redis 支持更丰富的数据结构,例如 hashes, lists, sets 等,同时支持数据持久化.除此 ...
- AD技巧之原理图元器件统一重新编号
本文将简要介绍Altium Designer中如何进行原理图元器件统一命名,这是Altium Designer软件一个小技巧,在学习和工程实践中,都十分有用的技能. 第一步:打开原理图 第二步:点击& ...
- 小白也能看懂的ArrayList的扩容机制
来,话不多说进入正题!我们下面用最简单的代码创建ArrayList并添加11个元素,并 一 一 讲解底层源码:在说之前,给大家先普及一些小知识: >ArrayList底层是用数组来实现的 > ...
- Matlab 中 imshow 函数
转自: https://blog.csdn.net/xiaochou87/article/details/43488829 matlab中显示图像的语句是: ...
- VS2015建立一个完整的c++工程:头文件.h 源文件.cpp,自动生成类
https://blog.csdn.net/weixin_40539125/article/details/81430801 打开VS2015 ,新建VS win32工程,前面步骤很简单,不再阐述 下 ...
- C++ format 函数
转载原文链接:https://blog.csdn.net/nowhaha/article/details/38710571 原博主很有心,文字标有颜色,奥利给! Thanks C++ format ...
- mysql字段大小写敏感设置
mysql中varchar类型的字符集一般设置成utf8,然而mysql默认是对大小写不敏感(不区分),如果想要mysql区分大小写需要设置排序规则,规则详解如下:在mysql中存在着各种排序规则:1 ...
- C# Socket TCP发送图片与接收图片
如果需要查看更多文章,请微信搜索公众号 csharp编程大全,需要进C#交流群群请加微信z438679770,备注进群, 我邀请你进群! ! ! --------------------------- ...
- 吐血分享一款免费看所有付费影视的app,不好用来石欠我
前言 朋友经常找我要各种付费影视资源,在下逛遍各大网站,终于找到一款app,那简直是神器啊. 几乎各大主流平台的付费影视都能观看,亲测有效.还在浏览器一个一个搜资源而费劲?? 还在为只买了一个平台的V ...
- git的项目完整操作
今天来说下项目中git 的使用,针对常规操作: 然后执行 git status 可以看到目前的状态: 再执行添加操作 git add . 添加所有文件 接着执行提交命令 git com ...