题目大意

  有一个网格(或者你可以认为这是一个图),每个点都有颜色 \(c_i\) 和点权 \(a_i\)。

  求最小的连通块,满足这个连通块内点的颜色数量 \(\geq k\)。在满足点数最少的前提下,要求点权的中位数最少。

  \(n\leq 233,c_i\leq n,k\leq 5\)

题解

  如果 \(c_i\) 很小,就可以直接用斯坦纳树做。

  本题要求在满足点数最少的前提下,要求点权的中位数最少。那么可以二分中位数 \(s\),将 \(a_i\leq s\) 的点的权值设为 \(M-1\),\(a_i>s\) 的点的权值设为 \(M+1\),其中 \(M\) 是一个很大的数。这样就可以在满足点数最小的前提下求出最小中位数是否 \(\leq s\)。

  还有一个问题是 \(c_i\) 比较大。我们可以把每一种颜色随机映射到 \([1,k]\) 中,当答案的 \(k\) 种颜色映射到 \([1,k]\) 中不同的值的时候就能求出正确答案。求一次正确的概率是 \(\frac{k!}{k^k}\),多求几次就好了。

  时间复杂度:\(O(T(3^kn+2^kn\log n)\log n)\)

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cstdlib>
  5. #include<ctime>
  6. #include<functional>
  7. #include<cmath>
  8. #include<vector>
  9. #include<assert.h>
  10. #include<queue>
  11. using namespace std;
  12. typedef long long ll;
  13. typedef unsigned long long ull;
  14. typedef double db;
  15. typedef long double ldb;
  16. typedef std::pair<int,int> pii;
  17. typedef std::pair<ll,ll> pll;
  18. void open(const char *s){
  19. #ifndef ONLINE_JUDGE
  20. char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
  21. #endif
  22. }
  23. void open2(const char *s){
  24. #ifdef DEBUG
  25. char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
  26. #endif
  27. }
  28. int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
  29. void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
  30. int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
  31. int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
  32. const int inf=0x3fffffff;
  33. const int N=300;
  34. int _n,_m;
  35. int n,k;
  36. int t;
  37. int a[N],c[N],d[N],e[N],b[N],vis[N];
  38. int a2[N],c2[N];
  39. int f[1<<5][N];
  40. vector<int> g[N];
  41. pii ans;
  42. queue<pii> q1,q2,q3;
  43. //priority_queue<pii,vector<pii>,greater<pii> > q;
  44. int id(int x,int y)
  45. {
  46. return (x-1)*_m+y;
  47. }
  48. vector<pii> h;
  49. int check(int v)
  50. {
  51. for(int i=1;i<=n;i++)
  52. if(a[i]<=v)
  53. a2[i]=100000-1;
  54. else
  55. a2[i]=100000+1;
  56. for(int i=0;i<1<<k;i++)
  57. for(int j=1;j<=n;j++)
  58. f[i][j]=inf;
  59. for(int i=1;i<=n;i++)
  60. if(c2[i]!=-1)
  61. f[1<<(c2[i]-1)][i]=0;
  62. for(int i=1;i<1<<k;i++)
  63. {
  64. for(int j=(i-1)&i;j;j=(j-1)&i)
  65. for(int l=1;l<=n;l++)
  66. f[i][l]=min(f[i][l],f[j][l]+f[i^j][l]);
  67. h.clear();
  68. for(int j=1;j<=n;j++)
  69. {
  70. h.push_back(pii(f[i][j],j));
  71. vis[j]=0;
  72. }
  73. sort(h.begin(),h.end());
  74. for(int i=0;i<n;i++)
  75. q3.push(h[i]);
  76. while(!q1.empty()||!q2.empty()||!q3.empty())
  77. {
  78. pii x;
  79. if(!q1.empty()&&(q2.empty()||(q1.front()<=q2.front()))&&(q3.empty()||(q1.front()<=q3.front())))
  80. {
  81. x=q1.front();
  82. q1.pop();
  83. }
  84. else if(!q2.empty()&&(q1.empty()||(q2.front()<=q1.front()))&&(q3.empty()||(q2.front()<=q3.front())))
  85. {
  86. x=q2.front();
  87. q2.pop();
  88. }
  89. else
  90. {
  91. x=q3.front();
  92. q3.pop();
  93. }
  94. if(vis[x.second])
  95. continue;
  96. vis[x.second]=1;
  97. f[i][x.second]=min(f[i][x.second],x.first);
  98. x.first+=a2[x.second];
  99. // for(auto v:g[x.second])
  100. for(vector<int>::iterator it=g[x.second].begin();it!=g[x.second].end();it++)
  101. {
  102. int v=*it;
  103. if(!vis[v])
  104. {
  105. if(a2[x.second]==100000-1)
  106. q1.push(pii(x.first,v));
  107. else
  108. q2.push(pii(x.first,v));
  109. }
  110. }
  111. }
  112. }
  113. int res=inf;
  114. for(int i=1;i<=n;i++)
  115. if(c2[i]!=-1)
  116. {
  117. f[(1<<k)-1][i]+=a2[i];
  118. res=min(res,f[(1<<k)-1][i]);
  119. }
  120. return res;
  121. }
  122. void gao()
  123. {
  124. for(int i=1;i<=n;i++)
  125. b[i]=rand()%k+1;
  126. for(int i=1;i<=n;i++)
  127. if(c[i]!=-1)
  128. c2[i]=b[c[i]];
  129. else
  130. c2[i]=-1;
  131. int l=1,r=t;
  132. int temp=check(1);
  133. if(temp==inf)
  134. return;
  135. int v=(int)round((db)temp/100000);
  136. if(v>ans.first)
  137. return;
  138. while(l<r)
  139. {
  140. int mid=(l+r)>>1;
  141. temp=check(mid);
  142. if(temp<=(int)round((db)temp/100000)*100000)
  143. r=mid;
  144. else
  145. l=mid+1;
  146. }
  147. ans=min(ans,pii(v,l));
  148. }
  149. void solve()
  150. {
  151. scanf("%d%d%d",&_n,&_m,&k);
  152. n=_n*_m;
  153. for(int i=1;i<=n;i++)
  154. scanf("%d",&c[i]);
  155. for(int i=1;i<=n;i++)
  156. {
  157. scanf("%d",&a[i]);
  158. d[i]=a[i];
  159. }
  160. sort(d+1,d+n+1);
  161. t=unique(d+1,d+n+1)-d-1;
  162. for(int i=1;i<=n;i++)
  163. a[i]=lower_bound(d+1,d+t+1,a[i])-d;
  164. for(int i=1;i<=n;i++)
  165. g[i].clear();
  166. for(int i=1;i<=_n;i++)
  167. for(int j=1;j<=_m;j++)
  168. if(c[id(i,j)]!=-1)
  169. {
  170. if(i>1&&c[id(i-1,j)]!=-1)
  171. g[id(i,j)].push_back(id(i-1,j));
  172. if(i<_n&&c[id(i+1,j)]!=-1)
  173. g[id(i,j)].push_back(id(i+1,j));
  174. if(j>1&&c[id(i,j-1)]!=-1)
  175. g[id(i,j)].push_back(id(i,j-1));
  176. if(j<_m&&c[id(i,j+1)]!=-1)
  177. g[id(i,j)].push_back(id(i,j+1));
  178. }
  179. ans=pii(inf,inf);
  180. for(int times=200;times;times--)
  181. gao();
  182. if(ans.first==inf)
  183. printf("-1 -1\n");
  184. else
  185. printf("%d %d\n",ans.first,d[ans.second]);
  186. }
  187. int main()
  188. {
  189. srand(19260817);
  190. open("chocolate");
  191. int t;
  192. scanf("%d",&t);
  193. while(t--)
  194. solve();
  195. return 0;
  196. }z

【THUSC2017】【LOJ2977】巧克力 斯坦纳树的更多相关文章

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

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

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

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

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

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

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

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

  5. 洛谷 P7450 - [THUSCH2017] 巧克力(斯坦纳树+随机化)

    洛谷题面传送门 9.13 补之前 8.23 做的题,不愧是鸽子 tzc( 首先我们先来探讨一下如果 \(c_{i,j}\le k\) 怎么做,先考虑第一问.显然一个连通块符合条件当且仅当它能够包含所有 ...

  6. 【BZOJ2595】游览计划(状压DP,斯坦纳树)

    题意:见题面(我发现自己真是越来越懒了) 有N*M的矩阵,每个格子有一个值a[i,j] 现要求将其中的K个点(称为关键点)用格子连接起来,取(i,j)的费用就是a[i,j] 求K点全部连通的最小花费以 ...

  7. HDU 4085 斯坦纳树

    题目大意: 给定无向图,让前k个点都能到达后k个点(保护地)中的一个,而且前k个点每个需要占据后k个中的一个,相互不冲突 找到实现这个条件达到的选择边的最小总权值 这里很容易看出,最后选到的边不保证整 ...

  8. hdu4085 Peach Blossom Spring 斯坦纳树,状态dp

    (1)集合中元素表示(1<<i), i从0开始 (2)注意dp[i][ss] = min(dp[i][ss], dp[i][rr | s[i]] + dp[i][(ss ^ rr) | s ...

  9. hdu 3311 斯坦纳树

    思路:虚拟一个0号节点,将每个点建一条到0号节点的边,权值为挖井需要的价值.并要保证0号节点同另外n个寺庙一样被选择即可. 然后就是求斯坦纳树了. #include<map> #inclu ...

随机推荐

  1. C# 数组Array

    数组是对相同类型的一组数据的封装.数组定义的时候,要说明是对哪一种类型的封装,并且要指定长度. using System; using System.Collections.Generic; usin ...

  2. 在表单提交之前做校验-利用jQuery的submit方法

    点击表单中的提交按钮,默认就会提交表单,如果要在表单提交之前做一些校验,那么就可以用jQuery的submit方法. 也就是jQuery的submit的方法执行顺序,在表单的提交之前.用法如下: $( ...

  3. Poj1799

    Yeehaa! Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 15082   Accepted: 6675 Descript ...

  4. 20190423-Vscode与Sass不得不说的秘密(>^ω^<)

    这是乱七八糟的前言:emmm,今天倔强的点,是关于Vscode使用easySass插件时,不安装ruby环境,直接使用插件编译时,不进行设置,分音是会转译为Css文件的= =,神坑的后知后觉才发现是因 ...

  5. [笔记]记录原开发工作在base命名空间下扩展的属性与方法

    前言 该笔记只是为了记录以前开发使用的方式. 处理命名空间namespace /** * 处理命名空间 * @param {string} 空间名称,可多个 * @return {object} 对象 ...

  6. K3日志定时备份

    K3日志超过5万条以后,每次用户登陆后,系统都会提示日志太多.但是日志又不能随意删除,所以需要做个数据库定时任务,定时把日志转移到备份表. declare @dt datetime;; SELECT ...

  7. C++ 子类继承父类纯虚函数、虚函数和普通函数的区别

    C++三大特性:封装.继承.多态,今天给大家好好说说继承的奥妙 1.虚函数: C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现.子类可以重写父类的虚函数实现子类 ...

  8. jquery实现静态柱形图(写死的数据,只为系统首页UI更美观)

    这段时间比较空闲,便阅读公司做好的项目的源代码,学习学习同事的开发思路. 在项目中使用图表可以很好地提高人机交互的友好度,开发的时候看到项目的首页有两个很小的柱形图,很漂亮,便找到对应的代码看了看,发 ...

  9. 使用make

    5.11 库的使用 代码的复用是计算机程序设计语言中的一个重要的概念.可以把编译好的目标文件模块统一放到一个库中,使得程序员可以在不同的程序中共享这些代码. 在Linux操作系统下,最后连接生成可执行 ...

  10. RobotFramework第二篇之web自动化

    (1)安装seleniumLibrary库: pip install --upgrade --pre robotframework-seleniumlibrary 使用第三方库关键字: (1)sett ...