P2765 魔术球问题

题目描述

«问题描述:

假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球。

(1)每次只能在某根柱子的最上面放球。

(2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。

试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。

«编程任务:

对于给定的n,计算在n根柱子上最多能放多少个球。

输入格式

第1 行有1个正整数n,表示柱子数。

输出格式

程序运行结束时,将n 根柱子上最多能放的球数以及相应的放置方案输出。文件的第一行是球数。接下来的n行,每行是一根柱子上的球的编号。

输入输出样例

输入 #1复制

4

输出 #1复制

11
1 8
2 7 9
3 6 10
4 5 11

说明/提示

4<=n<=55

思路:

首先知道放球的个数和柱子的个数是成正相关的,

一直增加球,对于每一个球i,将比其小的,能和其相加为平方数的,统一连中间边。

之所以叫中间边,是因为这题要拆点,设源点和汇点分别为S和T。

将每一个点i,拆为 Xi,Yi,

每一个点将其S与Xi连接,Yi与T连接,

中间点就是如果i节点和j节点相连接,

就Xi 与Yj,相连,。以上讲到的边,流量全为1.

当num个数建立的容量网络的最小边覆盖x>n时,即n个柱子无法覆盖掉num个数时,

结束加边操作,此时num-1,就是N个柱子能覆盖到的最大数字。

在dinic算法中增光路的过程中,记录每一个v,增广的下一个节节点u。

一路链状输出就是方法。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}} inline void getInt(int* p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
const int INF = (1 << 30);
const int MAXN = 400000;
int idx = 0, e[MAXN], f[MAXN], ne[MAXN], h[100000];
void add(int a, int b, int c) {
e[idx] = b, ne[idx] = h[a], f[idx] = c, h[a] = idx++;
e[idx] = a, ne[idx] = h[b], f[idx] = 0, h[b] = idx++;
}
int S, T, ch[MAXN], q[MAXN], nex[MAXN];
bool tell() {
memset(ch, -1, sizeof(ch));
int head = 0, tail = 0;
ch[q[0] = S] = 0;
while (head <= tail) {
int t = q[head++];
for (int i = h[t]; i != -1; i = ne[i]) {
if (ch[e[i]] == -1 && f[i]) {
ch[q[++tail] = e[i]] = ch[t] + 1;
}
}
}
return ch[T] != -1;
}
int zeng(int a, int b) {
if (a == T)return b;
int r = 0;
for (int i = h[a]; i != -1; i = ne[i]) {
if (ch[a] + 1 == ch[e[i]] && f[i]) {
int t = zeng(e[i], min(b - r, f[i]));
if (t > 0)
{
// 可找路径。
nex[a >> 1] = (e[i] >> 1);
}
f[i] -= t; r += t; f[i ^ 1] += t;
}
}
if (!r)ch[a] = -1;
return r;
}
int dinic() {
int r = 0, t = 0;
while (tell()) {
while (t = zeng(S, INF)) {
r += t;
}
}
return r;
}
void set_S_T(int s, int t)
{
S = s;
T = t;
}
void init()
{
memset(h, -1, sizeof(h));
memset(nex, -1, sizeof(nex));
}
int n;
int w[1000];
bool vis[maxn];
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
gbtb;
init();
S = 0;
T = 1e4 + 10;
cin >> n;
int now = 0;
int num = 0;
while (now <= n)
{
++num;
add(S, num << 1, 1);
add((num << 1) | 1, T, 1);
for (int i = sqrt(num) + 1; i * i < (num << 1); ++i)
{
add((i * i - num) << 1, (num << 1) | 1, 1);
}
int s = dinic();
if (!s)
{
w[++now] = num;
}
}
cout << num - 1 << endl;
int k;
repd(i, 1, n)
{
if (!vis[w[i]])
{
k = w[i];
cout << k;
vis[k] = 1;
while (nex[k] != -1 && nex[k] != (T) >> 1 )
{
k=nex[k];
vis[k]=1;
cout<<" "<<k;
}
cout<<endl;
}
}
return 0;
} inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
}
else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}

洛谷 P2765 魔术球问题 (dinic求最大流,最小边覆盖)的更多相关文章

  1. 洛谷 P2765 魔术球问题 解题报告

    P2765 魔术球问题 题目描述 问题描述: 假设有\(n\)根柱子,现要按下述规则在这\(n\)根柱子中依次放入编号为\(1,2,3,\dots\)的球. \((1)\) 每次只能在某根柱子的最上面 ...

  2. 洛谷 [P2765] 魔术球问题

    贪心做法 每次尽可能选择已经放过球的柱子 #include <iostream> #include <cstdio> #include <cstring> #inc ...

  3. 洛谷P2765魔术球问题 最小路径覆盖

    https://www.luogu.org/problemnew/show/P2765 看到这一题第一眼想到:这不是二分最大流吗,后来发现还有一种更快的方法. 首先如果知道要放多少个球求最少的柱子,很 ...

  4. 洛谷P2765 魔术球问题(最大流)

    传送门 %%%KSkun大佬 话说明明是网络流……这题竟然还有打表找规律和纯贪心AC的……都是神犇啊…… 来说一下如何建图.首先把每一个点拆成$X_i$和$Y_i$,然后$S$向$X_i$连一条容量为 ...

  5. 洛谷P2765 魔术球问题

    题目链接:https://www.luogu.org/problemnew/show/P2765 知识点: 最大流 解题思路: 本题所有边的容量均为 \(1\). 从 \(1\) 开始加入数字,将这个 ...

  6. 洛谷P2765 魔术球问题(贪心 最大流)

    题意 已经很简洁了吧. 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全 ...

  7. P2765 魔术球问题

    P2765 魔术球问题 贪心模拟就可以过.........好像和dinic没啥关系   找找规律发现可以贪心放.n又灰常小. 设答案=m 你可以$O(mn)$直接模拟过去 闲的慌得话可以像我用个$se ...

  8. P2765 魔术球问题 网络流二十四题重温

    P2765 魔术球问题 知识点::最小点覆盖 这个题目要拆点,这个不是因为每一个球只能用一次,而是因为我们要求最小点覆盖,所以要拆点来写. 思路: 首先拆点,然后就是开始建边,因为建边的条件是要求他们 ...

  9. Libre 6003 「网络流 24 题」魔术球 (网络流,最大流)

    Libre 6003 「网络流 24 题」魔术球 (网络流,最大流) Description 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只 ...

随机推荐

  1. Cocos Creator Android打包 apk

    这一篇讲的是用 Cocos Creator 编译器打包 Android APP 的时候遇到的一些问题,虽然说打包的过程不是很复杂,但是在其中还是会遇到各式各样的坑. 我们将项目用CCC(Cocos C ...

  2. java内存回收需要了解的知识

    你是否有过这样的经历,跑得好好的Java进程,突然就瘫痪了?多数Java进程瘫痪的原因可以从java虚拟机层面找到原因. 1.什么情况下会执行gc 为了了解我们的系统为什么会不停fgc,我们需要先了解 ...

  3. gdb调试工具学习

    GDB 是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较喜欢那种图形界面方式的,像VC.BCB等IDE的调试,但如果你是在 UNIX平台下做软件,你会发现GDB这个调试工具有比 ...

  4. [转帖]Linux cpufreq 机制了解

    Linux cpufreq 机制了解 https://www.cnblogs.com/armlinux/archive/2011/11/12/2396780.html 引用文章链接: http://w ...

  5. POJ 1015 Jury Compromise (记录路径的背包问题)

    (点击此处查看原题) 题意 为了审判某一个人,需要在n个人当中选出m个人组成陪审团,n个人中每个人都有作为起诉方的价值p和作为辩护方的价值d,为了保证公平性,要求m个人作为起诉方的价值之和P和作为辩护 ...

  6. PHP搭建B2C分销商城系统需要考虑哪些因素?(一)

    在网购日渐繁盛的今天,传统线下门店和代理分销越发显示出其弊端.此种情况下,进入互联网市场是最好的选择.入驻第三方平台成本太高,无法掌握自己的流量,所以搭建自己的分销平台成为众多企业的首选.搭建B2C分 ...

  7. thinkphp5.1中使用Bootstrap4分页样式修改

    1.找到thinkphp下的Boorstrap的源码 \thinkphp\library\think\paginator\driver\Bootstrap.php 2丶直接修改源码 <?php ...

  8. 【hash】Seek the Name, Seek the Fame

    [哈希和哈希表]Seek the Name, Seek the Fame 题目描述 The little cat is so famous, that many couples tramp over ...

  9. 安装gcc过程中遇到相互依赖的问题

    在离线安装gcc的时候需要安装一些包,但是在安装 glibc-common    glibc遇到一个很恶心的问题,这两个包相互依赖. 经查询才发现需要一起安装这两个依赖包.真是有趣的很 rpm -iv ...

  10. Web API 自动生成接口文档

    1.添加NuGet程序包 Microsoft ASP.NET Web API 2.2 Help Page      (这是微软官方的) A Simple Test Client for ASP.NET ...