【PowerOJ1739&网络流24题】魔术球问题(最大流)
题意:

思路:
0.【问题分析】
枚举答案转化为判定性问题,然后最小路径覆盖,可以转化成二分图最大匹配,从而用最大流解决。
【建模方法】
枚举答案A,在图中建立节点1..A。如果对于i<j有i+j为一个完全平方数,连接一条有向边(i,j)。该图是有向无环图,求最小路径覆盖。如果刚好满足最小路径覆盖数等于N,那么A是一个可行解,在所有可行
解中找到最大的A,即为最优解。
具体方法可以顺序枚举A的值,当最小路径覆盖数刚好大于N时终止,A-1就是最优解。
【建模分析】
由于是顺序放球,每根柱子上的球满足这样的特征,即下面的球编号小于上面球的编号。抽象成图论,把每个球看作一个顶点,就是编号较小的顶点向编号较大的顶点连接边,条件是两个球可以相邻,即
编号之和为完全平方数。每根柱子看做一条路径,N根柱子要覆盖掉所有点,一个解就是一个路径覆盖。
最小路径覆盖数随球的数量递增不递减,满足单调性,所以可以枚举答案(或二分答案),对于特定的答案求出最小路径覆盖数,一个可行解就是最小路径覆盖数等于N的答案,求出最大的可行解就是最
优解。本问题更适合枚举答案而不是二分答案,因为如果顺序枚举答案,每次只需要在残量网络上增加新的节点和边,再增广一次即可。如果二分答案,就需要每次重新建图,大大增加了时间复杂度。
输出方案时候不需要重新跑一遍,虽然最后的残余网络比答案多两个点和一些边,但合法那部分的残余网络还是一样的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef pair<ll,ll>P;
#define N 100010
#define M 3000000
#define INF 1e9
#define fi first
#define se second
#define MP make_pair
#define pb push_back
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1 const ll MOD=1e9+,inv2=(MOD+)/;
double eps=1e-;
int dx[]={-,,,};
int dy[]={,,-,}; int head[N],vet[M],len[M],nxt[M],dis[N],p[N],vis[N],tot,S,T,s; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} void add(int a,int b,int c)
{
nxt[++tot]=head[a];
vet[tot]=b;
len[tot]=c;
head[a]=tot; nxt[++tot]=head[b];
vet[tot]=a;
len[tot]=;
head[b]=tot;
} bool bfs()
{
queue<int>q;
//rep(i,1,s) dis[i]=-1;
rep(i,,s) dis[i]=dis[i+]=-;
dis[T]=-;
q.push(S),dis[S]=;
while(!q.empty())
{
int u=q.front();
q.pop();
int e=head[u];
while(e)
{
int v=vet[e];
if(len[e]&&dis[v]==-)
{
dis[v]=dis[u]+;
q.push(v);
}
e=nxt[e];
}
}
return dis[T]!=-;
} int dfs(int u,int aug)
{
if(u==T) return aug;
int e=head[u],val=,flow=;
while(e)
{
int v=vet[e];
if(len[e]&&dis[v]==dis[u]+)
{
int t=dfs(v,min(len[e],aug));
if(!t)
{
e=nxt[e];
continue;
}
flow+=t;
aug-=t;
len[e]-=t;
len[e^]+=t;
if(!aug) break;
}
e=nxt[e];
}
if(!flow) dis[u]=-;
return flow;
} int maxflow()
{
int res=;
while(bfs()) res+=dfs(S,INF);
return res;
} int main()
{
int n=read();
S=; T=;
rep(i,,T) head[i]=;
tot=;
s=;
int sum=;
while()
{
s++;
rep(i,,s-)
if(sqrt(s+i)==(int)sqrt(s+i)) add(i,s+,);
add(S,s,);
add(s+,T,);
sum+=maxflow();
int t=s-sum;
if(t>n) break;
}
printf("%d\n",s-);
rep(i,,s-)
{
int e=head[i];
while(e)
{
int v=vet[e];
if(!len[e]){p[i]=v-; break;}
e=nxt[e];
}
}
rep(i,,s-)
{
if(vis[i]) continue;
int u=i;
while(u!=-)
{
vis[u]=;
printf("%d ",u);
u=p[u];
}
printf("\n");
}
return ;
}
【PowerOJ1739&网络流24题】魔术球问题(最大流)的更多相关文章
- 网络流24题——魔术球问题 luogu 2765
题目描述:这里 这道题是网络流问题中第一个难点,也是一个很重要的问题 如果直接建图感觉无从下手,因为如果不知道放几个球我就无法得知该如何建图(这是很显然的,比如我知道 $1+48=49=7^2$ ,可 ...
- COGS396. [网络流24题]魔术球问题(简化版
问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平 ...
- [luogu2765 网络流24题] 魔术球问题 (dinic最大流)
传送门 题目描述 «问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之 ...
- 2018.10.14 loj#6012. 「网络流 24 题」分配问题(费用流)
传送门 费用流水题. 依然是照着题意模拟建边就行了. 为了练板子又重新写了一遍费用流. 代码: #include<bits/stdc++.h> #define N 305 #define ...
- 2018.10.14 loj#6011. 「网络流 24 题」运输问题(费用流)
传送门 费用流入门题. 直接按照题意模拟. 把货物的数量当做容量建边. 然后跑一次最小费用流和最大费用流就行了. 代码: #include<bits/stdc++.h> #define N ...
- 【COGS 461】[网络流24题] 餐巾 最小费用最大流
既然是最小费用最大流我们就用最大流来限制其一定能把每天跑满,那么把每个表示天的点向T连流量为其所需餐巾,费用为0的边,然后又与每天的餐巾对于买是无限制的因此从S向每个表示天的点连流量为INF,费用为一 ...
- 【PowerOJ1752&网络流24题】运输问题(费用流)
题意: 思路: [问题分析] 费用流问题. [建模方法] 把所有仓库看做二分图中顶点Xi,所有零售商店看做二分图中顶点Yi,建立附加源S汇T. 1.从S向每个Xi连一条容量为仓库中货物数量ai,费用为 ...
- LOJ6003 - 「网络流 24 题」魔术球
原题链接 Description 假设有根柱子,现要按下述规则在这根柱子中依次放入编号为的球. 每次只能在某根柱子的最上面放球. 在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法 ...
- LibreOJ 6003. 「网络流 24 题」魔术球 贪心或者最小路径覆盖
6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 ...
随机推荐
- Spoj 2798 Qtree3
一棵结点为黑色或白色的树,初始都是白色的.有两种操作 1 将一个结点换颜色 2 询问从根到结点u路径上面的第一个黑色点,没有则输出-1 InputIn the first line there are ...
- Python基础语法之常量与变量
一.变量的命名规则 只能以下划线,数字和字母组成,不可以是特殊字符: 不可以以数字开头: 关键字不可作为变量名: 变量名区分大小写: 要具有描述性: 二.常量 python中并没有关键字const,在 ...
- 机器学习实战-Logistics回归
Logistics回归:实战,有两个特征X0,X1.100个样本,进行Logistics回归 1.导入数据 def load_data_set(): """ 加载数据集 ...
- Linux 项目上线流程
命令行样式修改 1 打开配置文件vim /etc/bashrc2 添加配置信息PS1="\[\e[37;40m\][\[\e[32;1m\]\u\[\e[37;40m\]@\h \[\e[3 ...
- 为什么存储过程比sql语句效率高?
存储过程经过预编译处理 而SQL查询没有 SQL语句需要先被数据库引擎处理成低级的指令 然后才执行 -------------------------------------------------- ...
- jQuery与JavaScript与ajax三者的区别与联系(转)
原文链接: https://blog.csdn.net/qq_43154385/article/details/85003484 通过阅读,对于三者关系有一个比较清晰的认知,对于后期深入学习大有裨益 ...
- MySql日期加天数,小时,分钟...得到新的时间
在当前的日期上加三天,天数随便改: SELECT date_add(CURRENT_DATE(), interval 3 day); 在指定的日期上加三天: SELECT date_add('2014 ...
- Nginx 配置二级虚拟目录访问 Laravel 重写
server { listen 80; server_name _; root /opt/sites; index index.php index.html index.htm; etag on; g ...
- Python 入门之常用运算符
Python 入门之常用运算符 Python中的运算按种类可分为算数运算.比较运算.逻辑运算.赋值运算.成员运算.身份运算.位运算 1.常用运算符: (1)算数运算符: + - * / %(取余(模) ...
- 客户端通过url向后端传递参数
在前端我们不仅可以通过get请求携带参数的方式向服务端传数据: https://127.0.0.1/index/?id=1&name=alex Django也允许通过,path路径的方式向se ...