洛谷 [P2765] 魔术球问题
贪心做法
每次尽可能选择已经放过球的柱子
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int num[100][1000],n;
bool chk(const int &a,const int &b){
int t=sqrt(a+b);
return t*t==a+b;
}
int main(){
cin>>n;
int cnt=0;
while(++cnt){
bool f=0;
for(int i=1;i<=n;i++){
if(num[i][0]&&chk(num[i][num[i][0]],cnt)) num[i][++num[i][0]]=cnt,f=1;
if(f) break;
}
for(int i=1;i<=n;i++){
if(!num[i][0]) num[i][++num[i][0]]=cnt,f=1;
if(f) break;
}
if(!f) break;
}
printf("%d\n",cnt-1);
for(int i=1;i<=n;i++){
for(int j=1;j<=num[i][0];j++){
printf("%d ",num[i][j]);
}
printf("\n");
}
return 0;
}
网络流做法
我们可以将其转化成最小路径覆盖问题来做,
从小到大枚举答案,对于每一个新加进去的答案,寻找在已加进去的点中,满足题意的点,连一条边.
我们发现连好以后这是一个DAG图,其最小路径覆盖就是需要的最少柱子数,我们要找到一个最小路径覆盖<=n的最大解,即最后的答案
求最小路径覆盖可以用二分图做
这里有几个优化,具体见代码
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
int init(){
int rv=0,fh=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
rv=(rv<<1)+(rv<<3)+c-'0';
c=getchar();
}
return fh*rv;
}
const int MAXN=5000,MAXM=50005;
int head[MAXN],n,cur[MAXN],dep[MAXN],nume,s,t,maxflow;
queue<int> q;
bool f[MAXN];
struct edge{
int to,nxt,cap,flow;
}e[MAXM<<1];
void adde(int from,int to,int cap){
e[++nume].to=to;
e[nume].nxt=head[from];
head[from]=nume;
e[nume].cap=cap;
}
bool chk(const int &a,const int &b){
int t=sqrt(a+b);
return t*t==a+b;
}
bool bfs(){
memset(dep,0,sizeof(dep));
while(!q.empty()) q.pop();
q.push(s);dep[s]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!dep[v]&&e[i].flow<e[i].cap){
dep[v]=dep[u]+1;
if(v==t) return 1;//搜到汇点就结束,因为最新加进来的点一定在最前面,所以,搜到的这条路径就是新加进来的路径
q.push(v);
}
}
}
return 0;
}
int dfs(int u,int flow){
if(u==t) return flow;
int tot=0;
for(int &i=cur[u];i&&tot<flow;i=e[i].nxt){
int v=e[i].to;
if(dep[v]==dep[u]+1&&e[i].flow<e[i].cap){
if(int t=dfs(v,min(flow-tot,e[i].cap-e[i].flow))){
e[i].flow+=t;
e[((i-1)^1)+1].flow-=t;
tot+=t;
}
}
}
return tot;
}
void dinic(){
while(bfs()){
for(int i=s;i<=t;i++) cur[i]=head[i];
maxflow+=dfs(s,0x3f3f3f3f);
}
}
void print(int u){
printf("%d ",u);
f[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to-2000;
if(!f[v]&&e[i].flow){
print(v);
return;
}
}
}
int main(){
n=init();
s=0,t=4950;
int cnt=0;
while(++cnt){
adde(s,cnt,1);adde(cnt,s,0);
adde(cnt+2000,t,1);adde(t,cnt+2000,0);
for(int i=1;i<cnt;i++){
if(chk(i,cnt)){
adde(i,cnt+2000,1);
adde(cnt+2000,i,0);
}
}
dinic();
if(cnt-maxflow>n) break;
}
printf("%d\n",cnt-1);
for(int k=1;k<=n;k++){
for(int i=1;i<cnt;i++) if(!f[i]){
print(i);break;
}
printf("\n");
}
return 0;
}
洛谷 [P2765] 魔术球问题的更多相关文章
- 洛谷 P2765 魔术球问题 解题报告
P2765 魔术球问题 题目描述 问题描述: 假设有\(n\)根柱子,现要按下述规则在这\(n\)根柱子中依次放入编号为\(1,2,3,\dots\)的球. \((1)\) 每次只能在某根柱子的最上面 ...
- 洛谷 P2765 魔术球问题 (dinic求最大流,最小边覆盖)
P2765 魔术球问题 题目描述 «问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2 ...
- 洛谷P2765魔术球问题 最小路径覆盖
https://www.luogu.org/problemnew/show/P2765 看到这一题第一眼想到:这不是二分最大流吗,后来发现还有一种更快的方法. 首先如果知道要放多少个球求最少的柱子,很 ...
- 洛谷P2765 魔术球问题(最大流)
传送门 %%%KSkun大佬 话说明明是网络流……这题竟然还有打表找规律和纯贪心AC的……都是神犇啊…… 来说一下如何建图.首先把每一个点拆成$X_i$和$Y_i$,然后$S$向$X_i$连一条容量为 ...
- 洛谷P2765 魔术球问题(贪心 最大流)
题意 已经很简洁了吧. 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全 ...
- 洛谷P2765 魔术球问题
题目链接:https://www.luogu.org/problemnew/show/P2765 知识点: 最大流 解题思路: 本题所有边的容量均为 \(1\). 从 \(1\) 开始加入数字,将这个 ...
- P2765 魔术球问题
P2765 魔术球问题 贪心模拟就可以过.........好像和dinic没啥关系 找找规律发现可以贪心放.n又灰常小. 设答案=m 你可以$O(mn)$直接模拟过去 闲的慌得话可以像我用个$se ...
- P2765 魔术球问题 网络流二十四题重温
P2765 魔术球问题 知识点::最小点覆盖 这个题目要拆点,这个不是因为每一个球只能用一次,而是因为我们要求最小点覆盖,所以要拆点来写. 思路: 首先拆点,然后就是开始建边,因为建边的条件是要求他们 ...
- [洛谷P2113] 看球泡妹子
洛谷题目链接:看球泡妹子 题目背景 2014年巴西世界杯开幕了,现在满城皆是世界杯,商家们利用它大赚一笔,小明和小红也借此机会增进感情. 题目描述 本届世界杯共有N支球队,M场比赛.男球迷小明喜欢看比 ...
随机推荐
- SpringMVC框架学习笔记(2)——使用注解开发SpringMVC
1.配置web.xml <servlet> <servlet-name>mvc</servlet-name> <servlet-class>org.sp ...
- 分布式计算框架学习笔记--hadoop工作原理
(hadoop安装方法:http://blog.csdn.net/wangjia55/article/details/53160679这里不再累述) hadoop是针对大数据设计的一个计算架构.如果你 ...
- [Golang]一道考察defer与命名返回值的题目
题目 输出: 4 1 3 解释 当函数有可命名结果形参时,结果形参的初始值被设置为零值,函数的return语句会设置结果形参的值 当函数有可命名结果形参时,defer函数是可以修改它,然后再将它的值返 ...
- [国嵌攻略][160][SPI驱动程序设计]
SPI Flash驱动 1.打开/drivers/mtd/devices/m25p80.c驱动文件.找到初始化m25p80_init函数,其中通过spi_register_driver来注册spi设备 ...
- Android 通知 相关api记录
记录帖 通知(Notification) 的API 1.使用getSystemService()方法获取系统服务,参数接收一个字符串来确定获取具体的服务,使用通知传入Content.NOTIFICAT ...
- Tomcat配置虚拟路径访问容器外的硬盘资源
问题: 如果tomcat中上传了很多的图片,会导致tomcat启动的时候会慢,所以应该把图片上传到tomcat容器外部 那么,问题来了: tomcat出于安全考虑,禁止了直接访问外部硬盘资源. 解决: ...
- Python3 的列表
1:列表: Python的列表比C语言的数组强大的多,数组只能存放相同类型的数据,而列表则像一个大集装箱可以存放整形.浮点型.字符串.对象等 2:创建列表的方法 #创建一个普通列表 list1=[1, ...
- phpwind9.0升级到php7后出现的问题修复
最近将一个两年多以前的用phpwind9.0搭建的论坛升级到php7,遇到了页面无法打开,显示为500错误,排查了一整天时间,终于解决! 1.打开文件:src/applications/appcent ...
- Struts的session问题
问题描述: 在一个action中设置session之后,在jsp中得不到session的值或者在另一个action中得不到session的值. 解决方案: 1.不要把session设置成为静态的,同时 ...
- UltraEdit激活方法
按照UltraEdit 并下载注册机后. 打开UltraEdit 弹出产品是使用 然后点击 输入注册码, 重点:断开网络 点击激活,弹出 离线激活选项. 用户名密码随意输入,打开注册机,把下面的 ...