【THUSC2017】【LOJ2977】巧克力 斯坦纳树
题目大意
有一个网格(或者你可以认为这是一个图),每个点都有颜色 \(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)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<functional>
#include<cmath>
#include<vector>
#include<assert.h>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
void open(const char *s){
#ifndef ONLINE_JUDGE
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
void open2(const char *s){
#ifdef DEBUG
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
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;}
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');}
int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
const int inf=0x3fffffff;
const int N=300;
int _n,_m;
int n,k;
int t;
int a[N],c[N],d[N],e[N],b[N],vis[N];
int a2[N],c2[N];
int f[1<<5][N];
vector<int> g[N];
pii ans;
queue<pii> q1,q2,q3;
//priority_queue<pii,vector<pii>,greater<pii> > q;
int id(int x,int y)
{
return (x-1)*_m+y;
}
vector<pii> h;
int check(int v)
{
for(int i=1;i<=n;i++)
if(a[i]<=v)
a2[i]=100000-1;
else
a2[i]=100000+1;
for(int i=0;i<1<<k;i++)
for(int j=1;j<=n;j++)
f[i][j]=inf;
for(int i=1;i<=n;i++)
if(c2[i]!=-1)
f[1<<(c2[i]-1)][i]=0;
for(int i=1;i<1<<k;i++)
{
for(int j=(i-1)&i;j;j=(j-1)&i)
for(int l=1;l<=n;l++)
f[i][l]=min(f[i][l],f[j][l]+f[i^j][l]);
h.clear();
for(int j=1;j<=n;j++)
{
h.push_back(pii(f[i][j],j));
vis[j]=0;
}
sort(h.begin(),h.end());
for(int i=0;i<n;i++)
q3.push(h[i]);
while(!q1.empty()||!q2.empty()||!q3.empty())
{
pii x;
if(!q1.empty()&&(q2.empty()||(q1.front()<=q2.front()))&&(q3.empty()||(q1.front()<=q3.front())))
{
x=q1.front();
q1.pop();
}
else if(!q2.empty()&&(q1.empty()||(q2.front()<=q1.front()))&&(q3.empty()||(q2.front()<=q3.front())))
{
x=q2.front();
q2.pop();
}
else
{
x=q3.front();
q3.pop();
}
if(vis[x.second])
continue;
vis[x.second]=1;
f[i][x.second]=min(f[i][x.second],x.first);
x.first+=a2[x.second];
// for(auto v:g[x.second])
for(vector<int>::iterator it=g[x.second].begin();it!=g[x.second].end();it++)
{
int v=*it;
if(!vis[v])
{
if(a2[x.second]==100000-1)
q1.push(pii(x.first,v));
else
q2.push(pii(x.first,v));
}
}
}
}
int res=inf;
for(int i=1;i<=n;i++)
if(c2[i]!=-1)
{
f[(1<<k)-1][i]+=a2[i];
res=min(res,f[(1<<k)-1][i]);
}
return res;
}
void gao()
{
for(int i=1;i<=n;i++)
b[i]=rand()%k+1;
for(int i=1;i<=n;i++)
if(c[i]!=-1)
c2[i]=b[c[i]];
else
c2[i]=-1;
int l=1,r=t;
int temp=check(1);
if(temp==inf)
return;
int v=(int)round((db)temp/100000);
if(v>ans.first)
return;
while(l<r)
{
int mid=(l+r)>>1;
temp=check(mid);
if(temp<=(int)round((db)temp/100000)*100000)
r=mid;
else
l=mid+1;
}
ans=min(ans,pii(v,l));
}
void solve()
{
scanf("%d%d%d",&_n,&_m,&k);
n=_n*_m;
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
d[i]=a[i];
}
sort(d+1,d+n+1);
t=unique(d+1,d+n+1)-d-1;
for(int i=1;i<=n;i++)
a[i]=lower_bound(d+1,d+t+1,a[i])-d;
for(int i=1;i<=n;i++)
g[i].clear();
for(int i=1;i<=_n;i++)
for(int j=1;j<=_m;j++)
if(c[id(i,j)]!=-1)
{
if(i>1&&c[id(i-1,j)]!=-1)
g[id(i,j)].push_back(id(i-1,j));
if(i<_n&&c[id(i+1,j)]!=-1)
g[id(i,j)].push_back(id(i+1,j));
if(j>1&&c[id(i,j-1)]!=-1)
g[id(i,j)].push_back(id(i,j-1));
if(j<_m&&c[id(i,j+1)]!=-1)
g[id(i,j)].push_back(id(i,j+1));
}
ans=pii(inf,inf);
for(int times=200;times;times--)
gao();
if(ans.first==inf)
printf("-1 -1\n");
else
printf("%d %d\n",ans.first,d[ans.second]);
}
int main()
{
srand(19260817);
open("chocolate");
int t;
scanf("%d",&t);
while(t--)
solve();
return 0;
}z
【THUSC2017】【LOJ2977】巧克力 斯坦纳树的更多相关文章
- loj2977 巧克力 (斯坦纳树+随机化)
考虑颜色比较少的时候,第一问可以直接斯坦纳树 第二问考虑二分,每次把每格的权值给成1000+[a[i]>m],就是在个数最少的基础上尽量选小于等于m的 然而颜色太多不能直接做,但可以把每种颜色映 ...
- [THUSC2017]巧克力[斯坦纳树、随机化]
题意 题目链接 分析 对于第一问,如果颜色数量比较少的话可以 \(\binom{cnt}{k}\) 枚举最终连通块中的 \(k\) 种颜色,然后利用斯坦纳树求解. 如果颜色比较多,考虑将所有的颜色重新 ...
- LOJ#2977. 「THUSCH 2017」巧克力(斯坦纳树+随机化)
题目 题目 做法 考虑部分数据(颜色较少)的: 二分中位数\(mid\),将\(v[i]=1000+(v[i]>mid)\) 具体二分操作:然后求出包含\(K\)种颜色的联通快最小的权值和,判断 ...
- LOJ 2997 「THUSCH 2017」巧克力——思路+随机化+斯坦纳树
题目:https://loj.ac/problem/2977 想到斯坦纳树.但以为只能做 “包含一些点” 而不是 “包含一些颜色” .而且不太会处理中位数. 其实 “包含一些颜色” 用斯坦纳树做也和普 ...
- 洛谷 P7450 - [THUSCH2017] 巧克力(斯坦纳树+随机化)
洛谷题面传送门 9.13 补之前 8.23 做的题,不愧是鸽子 tzc( 首先我们先来探讨一下如果 \(c_{i,j}\le k\) 怎么做,先考虑第一问.显然一个连通块符合条件当且仅当它能够包含所有 ...
- 【BZOJ2595】游览计划(状压DP,斯坦纳树)
题意:见题面(我发现自己真是越来越懒了) 有N*M的矩阵,每个格子有一个值a[i,j] 现要求将其中的K个点(称为关键点)用格子连接起来,取(i,j)的费用就是a[i,j] 求K点全部连通的最小花费以 ...
- HDU 4085 斯坦纳树
题目大意: 给定无向图,让前k个点都能到达后k个点(保护地)中的一个,而且前k个点每个需要占据后k个中的一个,相互不冲突 找到实现这个条件达到的选择边的最小总权值 这里很容易看出,最后选到的边不保证整 ...
- 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 ...
- hdu 3311 斯坦纳树
思路:虚拟一个0号节点,将每个点建一条到0号节点的边,权值为挖井需要的价值.并要保证0号节点同另外n个寺庙一样被选择即可. 然后就是求斯坦纳树了. #include<map> #inclu ...
随机推荐
- axios(封装使用、拦截特定请求、判断所有请求加载完毕)
博客地址:https://ainyi.com/71 基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 Node.js 中使用 vue2.0之后,就不再对 vue-resource 更新 ...
- 创建索引CreateIndex
nuget引用NEST new一个客户端 源码可查ElasticClient.cs new一个ElasticClient有多种方式 第一种 ES地址是http://localhost:9200,可以直 ...
- 利用StackExchange.Redis和Log4Net构建日志队列
简介:本文是一个简单的demo用于展示利用StackExchange.Redis和Log4Net构建日志队列,为高并发日志处理提供一些思路. 0.先下载安装Redis服务,然后再服务列表里启动服务(R ...
- Docker+SpringBoot远程发布
Docker+SpringBoot远程发布 发布成功后启动: docker run -di --name demo1.1 -p 8080:8085 demo:1.0 docker run 命令大全:h ...
- jQuery元素操作
jQuery中创建元素及追加元素 DOM中可以动态创建元素:document.createElement(“标签的名字”); jQuery中同样可以创建元素标签,并且返回的就是jQuery对象,可以直 ...
- android 权限库EasyPermissions
文章链接:https://mp.weixin.qq.com/s/H63Sn03xV0JoINXB4SWWKA 众所周知,在android 6.0之后,如果应用程序需要危险权限,则用户必须明确向应用授予 ...
- Microsoft SQL Server 2016 RC3 安装
首先下载SQL Server 2016 RC3 安装iso 下载链接 ed2k://|file|cn_sql_server_2016_rc_3_x64_dvd_8566578.iso|24648232 ...
- DVWA 黑客攻防演练(十三)JS 攻击 JavaScript Attacks
新版本的 DVWA 有新东西,其中一个就是这个 JavaScript 模块了. 玩法也挺特别的,如果你能提交 success 这个词,成功是算你赢了.也看得我有点懵逼. 初级 如果你改成 " ...
- Oracl 一条sql语句 批量添加、修改数据
最近一直在用,也一直在学oralc,项目上也用到了批量的添加(读取上传CSV文件信息,把符合条件的信息写入到数据库中),在写的时候想到了可能是数据量大就想该怎么快,(由于本人在.NET开发期间没有做过 ...
- git window安装与注册邮箱用户名
1.git window版本下载 https://git-scm.com/downlods 下载完后点击安装包安装,一直下一步就行; 2.验证安装是否成功 在开始菜单里找到“Git”->“Git ...