洛谷题面传送门

9.13 补之前 8.23 做的题,不愧是鸽子 tzc(

首先我们先来探讨一下如果 \(c_{i,j}\le k\) 怎么做,先考虑第一问。显然一个连通块符合条件当且仅当它能够包含所有颜色。我们注意到这里的 \(k\) 数据范围很小,因此考虑状压 \(dp\)。\(dp_{x,y,S}\) 表示包含 \((x,y)\) 且囊括了 \(S\) 中所有颜色的最小连通块的大小。那么有转移 \(dp_{x,y,S}+1\to dp_{x+1,y,S\cup\{c_{x+1,y}\}}\),其余三个方向上的转移也同理。注意这样直接转移有后效性,不过注意到这种后效性只可能发生在 \(c_{x+1,y}\in S\) 的情况,因此我们考虑这样转移:从小到大枚举 \(S\),然后对于每个 \(dp_{x,y,S}\) 更新 \(dp_{x,y,S}=\min\limits_{S_1\cup S_2=S}\{dp_{x,y,S_1}+dp_{x,y,S_2}-1\}\),之后再用 \(dp_{x,y,S}\) 去更新周围的点,即 \(dp_{x,y+1,S}\leftarrow dp_{x,y,S}+1\),类似于一个最短路的过程。不难发现上述过程中使用了取 \(\min/\max\) 的 DP 的一个思想:我的 DP 转移贡献不一定合法,但我不合法的情况肯定没有合法的情况来得更优。在上面的 DP 转移中有可能出现转移到的 \(S\) 等于我们转移所产生贡献的连通块真正包含的颜色集合,但这个包含关系是必然成立的,因此最优解肯定会被我囊括在内。据说这就是斯坦纳树的基本思想?反正也算一个非常 trivial 的知识点吧(

接下来考虑第二问。其实也非常套路吧……考虑二分中位数 \(mid\),然后把 \(\le mid\) 都设为 \(-1\),\(>mid\) 都设为 \(1\),这样可以仿照之前的解法求出在满足连通块大小最小的情况,最小的权值和,如果最小权值和 \(\le 0\) 则说明这个中位数符合条件,应向左二分,否则应向右二分。正确性显然,总复杂度大概是 \(2^k·\log^2(nm)·nm\)​。

接下来考虑原问题。显然对于原题的数据范围而言,直接上个状压 dp 就不可取了。不过这个思想还是很有启发意义的。考虑最优解连通块中的颜色种类 \(S\),我们希望能够重新分组使得颜色个数 \(\le k\),并且恰好满足 \(S\) 中的颜色被分在了至少 \(k\) 组中,有什么好方法呢?随机化,考虑随机将 \(nm\) 种颜色分组,那么最优解刚好被分在 \(k\) 个不同的组中的概率大概是 \(\dfrac{k!}{k^k}\),当 \(k=5\) 时这个概率大概在百分之几,随机个 \(150\) 次出错的概率就很低了。

时间复杂度 \(T·150·2^k·\log^2(nm)·nm\)​,非常卡常。然后我反向套路一波,把 dij 换成 SPFA(真·网格图 SPFA)就过了(?)

const int MAXN=233;
const int MAXP=32;
const int INF=1061109567;
const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};
int n,m,k,a[MAXN+5][MAXN+5],c[MAXN+5][MAXN+5];
int va[MAXN+5],col[MAXN+5],id[MAXN+5][MAXN+5],cc[MAXN+5],cnt=0;
int hd[MAXN+5],to[MAXN*4+5],nxt[MAXN*4+5],ec=0;
void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
bool vis[MAXN+5];
pii dp[MAXN+5][MAXP+5],b[MAXN+5];
pii operator +(pii x,pii y){return mp(x.fi+y.fi,x.se+y.se);}
pii operator -(pii x,pii y){return mp(x.fi-y.fi,x.se-y.se);}
void dijkstra(int s){
queue<int> q;
for(int i=1;i<=cnt;i++) q.push(i),vis[i]=1;
while(!q.empty()){
int x=q.front();q.pop();vis[x]=0;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];
if(dp[y][s]>dp[x][s]+b[y]){
dp[y][s]=dp[x][s]+b[y];
if(!vis[y]) vis[y]=1,q.push(y);
}
}
}
}
pii check(int mid){
for(int i=1;i<=cnt;i++) for(int s=0;s<(1<<k);s++) dp[i][s]=mp(INF,INF);
for(int i=1;i<=cnt;i++){
if(va[i]<=mid) dp[i][1<<(col[i]-1)]=dp[i][0]=b[i]=mp(1,-1);
else dp[i][1<<(col[i]-1)]=dp[i][0]=b[i]=mp(1,1);
}
for(int s=0;s<(1<<k);s++){
for(int i=1;i<=cnt;i++){
for(int t=(s-1)&s;t;t=(t-1)&s) chkmin(dp[i][s],dp[i][t]+dp[i][s^t]-b[i]);
} dijkstra(s);
} pii res=mp(INF,INF);
for(int i=1;i<=cnt;i++) chkmin(res,dp[i][(1<<k)-1]);
return res;
}
pii work(){
int l=0,r=1e6,res=check(0).fi,p=INF;
if(res==INF) return mp(INF,INF);
while(l<=r){
int mid=l+r>>1;
if(check(mid).se<=0) p=mid,r=mid-1;
else l=mid+1;
}
return mp(res,p);
}
void clear(){
memset(hd,0,sizeof(hd));ec=0;
memset(id,0,sizeof(id));cnt=0;
}
void solve(){
scanf("%d%d%d",&n,&m,&k);pii res=mp(INF,INF);clear();
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&c[i][j]);
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(~c[i][j]) id[i][j]=++cnt,va[cnt]=a[i][j];
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int d=0;d<4;d++){
int x=i+dx[d],y=j+dy[d];
if(x<1||x>n||y<1||y>m||!id[x][y]) continue;
adde(id[i][j],id[x][y]);
}
int ______=150;
while(______--){
for(int i=1;i<=n*m;i++) cc[i]=rand()%k+1;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
if(id[i][j]) col[id[i][j]]=cc[c[i][j]];
chkmin(res,work());
} if(res.fi==INF) printf("-1 -1\n");
else printf("%d %d\n",res.fi,res.se);
}
int main(){
srand(20210823183524ll&4294967295);
int qu;scanf("%d",&qu);while(qu--) solve();
return 0;
}

洛谷 P7450 - [THUSCH2017] 巧克力(斯坦纳树+随机化)的更多相关文章

  1. loj2977 巧克力 (斯坦纳树+随机化)

    考虑颜色比较少的时候,第一问可以直接斯坦纳树 第二问考虑二分,每次把每格的权值给成1000+[a[i]>m],就是在个数最少的基础上尽量选小于等于m的 然而颜色太多不能直接做,但可以把每种颜色映 ...

  2. LOJ#2977. 「THUSCH 2017」巧克力(斯坦纳树+随机化)

    题目 题目 做法 考虑部分数据(颜色较少)的: 二分中位数\(mid\),将\(v[i]=1000+(v[i]>mid)\) 具体二分操作:然后求出包含\(K\)种颜色的联通快最小的权值和,判断 ...

  3. 【THUSC2017】【LOJ2977】巧克力 斯坦纳树

    题目大意 有一个网格(或者你可以认为这是一个图),每个点都有颜色 \(c_i\) 和点权 \(a_i\). 求最小的连通块,满足这个连通块内点的颜色数量 \(\geq k\).在满足点数最少的前提下, ...

  4. [THUSC2017]巧克力[斯坦纳树、随机化]

    题意 题目链接 分析 对于第一问,如果颜色数量比较少的话可以 \(\binom{cnt}{k}\) 枚举最终连通块中的 \(k\) 种颜色,然后利用斯坦纳树求解. 如果颜色比较多,考虑将所有的颜色重新 ...

  5. 【BZOJ2595_洛谷4294】[WC2008]游览计划(斯坦纳树_状压DP)

    上个月写的题qwq--突然想写篇博客 题目: 洛谷4294 分析: 斯坦纳树模板题. 简单来说,斯坦纳树问题就是给定一张有边权(或点权)的无向图,要求选若干条边使图中一些选定的点连通(可以经过其他点) ...

  6. 洛谷P3264 [JLOI2015]管道连接(斯坦纳树)

    传送门 感觉对斯坦纳树还是有很多疑惑啊…… 等到时候noip没有爆零的话再回来填坑好了 //minamoto #include<iostream> #include<cstdio&g ...

  7. 洛谷P3264 [JLOI2015]管道连接 (斯坦纳树)

    题目链接 题目大意:有一张无向图,每条边有一定的花费,给出一些点集,让你从中选出一些边,用最小的花费将每个点集内的点相互连通,可以使用点集之外的点(如果需要的话). 算是斯坦纳树的入门题吧. 什么是斯 ...

  8. LOJ 2997 「THUSCH 2017」巧克力——思路+随机化+斯坦纳树

    题目:https://loj.ac/problem/2977 想到斯坦纳树.但以为只能做 “包含一些点” 而不是 “包含一些颜色” .而且不太会处理中位数. 其实 “包含一些颜色” 用斯坦纳树做也和普 ...

  9. [APIO2013]机器人(斯坦纳树)

    题目描述 VRI(Voltron 机器人学会)的工程师建造了 n 个机器人.任意两个兼容的机 器人站在同一个格子时可以合并为一个复合机器人. 我们把机器人用 1 至 n 编号(n ≤ 9).如果两个机 ...

随机推荐

  1. nmap常用命令汇总

    nmap常用命令 选项 解释 使用举例 举例说明 Nmap主机发现 -sP Ping扫描     -P0 无Ping扫描     -PS TCP SYN Ping扫描     -PA TCP ACK ...

  2. 4.19——数组双指针——26. 删除有序数组中的重复项 & 27. 删除有序数组中的重复项II & 80. 删除有序数组中的重复项 II

    第一次做到数组双指针的题目是80: 因为python的List是可以用以下代码来删除元素的: del List[index] 所以当时的我直接用了暴力删除第三个重复元素的做法,大概代码如下: n = ...

  3. python打印爱心

    print('\n'.join([''.join([('AndyLove'[(x-y)%8]if((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3 ...

  4. 牛客网 剑指Offer 索引

    二维数组中的查找 替换空格 从尾到头打印链表 重建二叉树 用两个栈实现队列 旋转数组的最小数字 斐波那契数列 跳台阶 变态跳台阶 矩形覆盖 二进制中1的个数 数值的整数次方 调整数组顺序使奇数位于偶数 ...

  5. Django(74)drf-spectacular自动生成接口文档

    介绍 drf-spectacular是为Django REST Framework生成合理灵活的OpenAPI 3.0模式.它可以自动帮我们提取接口中的信息,从而形成接口文档,而且内容十分详细,再也不 ...

  6. Pycharm的安装简介

    Pycharm 1. Pycharm简介 PyCharm是由JetBrains打造的一款Python IDE,VS2010的重构插件Resharper就是出自JetBrains之手.同时支持Googl ...

  7. Oracle 19c 单机

    环境 vm虚拟机 双磁盘 操作系统 Oracle Linux 7.9 操作系统安装带图形 选择中文,注意不要新建用户 关闭防火墙 selinux 配置好IP 挂载系统盘镜像 修改主机名 配置hosts ...

  8. Mysql 5.7 集群部署,keepalived

    参考文章: https://blog.csdn.net/f18770366447/article/details/80703347 https://www.cnblogs.com/benjamin77 ...

  9. pip切换源

    pip国内的一些镜像 阿里云http://mirrors.aliyun.com/pypi/simple/ 中国科技大学https://pypi.mirrors.ustc.edu.cn/simple/ ...

  10. OpenHarmony LiteOS C-SKY指令集移植指北

    摘要:本文介绍在OpenHarmony社区LiteOS-M项目中新增C-SKY指令集的开发流程,以及适配相应qemu工程的方法和步骤,供LiteOS内核相关开发者学习交流. 本文分享自华为云社区< ...