P2765 魔术球问题

这道题目,一眼看上去,并不能用网络流做

但是我们发现,如果将每个点拆成x和x‘

然后x连源点,x‘连汇点 都用容量为一的边

再然后是找这个数可以与那个数组成完全平方数,然后将这个数i与x‘连边

每加入一个点就跑一次最大流

那么如果可以塞进原柱,那么最大流就得到1否则为0

那么我们在得到0的时候新建柱子即可

另外,我们要注意

在判断完全平方数的时候

sqrt(ge+i)*sqrt(ge+i)==ge+i

这样判断在Windows下是正确的

但在Linux下要写成(int)sqrt(ge+i)*sqrt(ge+i)==ge+i

总体实现如下:

#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long ll;
inline ll read()
{
    register ll p(1),a(0);register char ch=getchar();
    while((ch<‘0‘||ch>‘9‘)&&ch!=‘-‘) ch=getchar();
    if(ch==‘-‘) p=-1,ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘) a=a*10+ch-48,ch=getchar();
    return a*p;
}
const int N=100100;
queue<int> Q;
int src=0,n,num,st=50014,d[N],head[N],pre[N],cnt=1,ge,jl[N],book[N];
struct EDGE{int nxt,val,to;}e[N];
void add(int u,int v,int w){e[++cnt]=(EDGE){head[u],w,v};head[u]=cnt;}
int BFS()
{
    while(!Q.empty()) Q.pop();Q.push(src);
    memset(d,-1,sizeof(d));d[src]=0;int u;
    while(!Q.empty())
    {
        u=Q.front();Q.pop();
        for(int i=head[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to) if(e[i].val&&d[v]==-1)
        {
            d[v]=d[u]+1;
            if(v==st) return 1;
            Q.push(v);
        }
    }
    return 0;
}
int DFS(int u,int flow)
{
    if(u==st||flow==0) return flow;
    int res=flow,tt;
    for(int i=head[u],v=e[i].to;i&&res;i=e[i].nxt,v=e[i].to) if(e[i].val&&d[v]==d[u]+1)
    {
        tt=DFS(v,min(res,e[i].val));
        if(!tt) d[v]=-1;
        if(tt&&v!=st) pre[u>>1]=v>>1;
        e[i].val-=tt;e[i^1].val+=tt;
        res-=tt;
    }
    return flow-res;
}
int Dinic()
{
    int all=0;
    while(BFS()) all+=DFS(src,0x3f3f3f3f);
    return all;
}
int main()
{
    // freopen("input","r",stdin);
    // freopen("output","w",stdout);
    n=read();
    while(num<=n)
    {
        ++ge;
        add(src,ge<<1,1);add(ge<<1,src,0);
        add(ge<<1|1,st,1);add(st,ge<<1|1,0);
        for(int i=1;i<ge;++i) if((int)sqrt(ge+i)*sqrt(ge+i)==ge+i)
        {
            add(i<<1,ge<<1|1,1);
            add(ge<<1|1,i<<1,0);
        }
        if(!Dinic()) jl[++num]=ge;
    }
    printf("%d\n",--ge);
    for(int i=1;i<=n;i++)
    {
        if(book[jl[i]]) continue;
        int tt=jl[i];book[tt]=1;
        while(tt) printf("%d ",tt),book[tt=pre[tt]]=1;
        printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/cold-cold/p/10213588.html

时间: 2024-10-08 05:13:05

P2765 魔术球问题的相关文章

【Luogu】P2765魔术球问题(没看懂的乱搞)

题目链接 这题……讲道理我没看懂. 不过我看懂题解的代码是在干嘛了qwq 题解是zhaoyifan的题解 然后……我来讲讲这个题解好了. 题解把值为i的球拆成了两个,一个编号是i*2,一个编号是i*2+1. 为什么编号要这么编呢?因为统计编号的时候好统计qwq 然后从起点向i*2连一条边,从i*2+1到终点连一条边. 然后对于能够跟他凑成完全平方数的连边. 然后跑最大流,如果发现这个球不能串进原来的柱子上,也就是说最大流没有变化,那么就新加一条柱子. 当柱子数超过n的时候就退出循环开始统计. 大

网络流二十四题之魔术球问题

P2765 魔术球问题 题目描述 «问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可放11 个球. «编程任务: 对于给定的n,计算在n根柱子上最多能放多少个球. 输入输出格式 输入格式: 第1 行有1个正整数n,表示柱子数. 输出格式: 程序运行结束时,将n 根柱子上最

POWOJ 1739: 魔术球问题 DAG最小路径覆盖转最大流

1739: 魔术球问题 题意: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.对于给定的n,计算在n根柱子上最多能放多少个球. tags: 对大佬来说应该是很素的一道题,但某还是花了好多时间才做出来.. 一开始连建图都有点懵,然后最小路径还是新概念,最大匹配也不太懂,最大流倒是会一点. 然后要打印答案,也不

【网络流24题】魔术球问题

P1226 - [网络流24题]魔术球问题 Description 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可 放11个球. ′编程任务: 对于给定的n,计算在 n根柱子上最多能放多少个球. Input 第1 行有 1个正整数n,表示柱子数. Output 第一行是球

cogs_396_魔术球问题_(最小路径覆盖+二分图匹配,网络流24题#4)

描述 http://cojs.tk/cogs/problem/problem.php?pid=396 连续从1开始编号的球,按照顺寻一个个放在n个柱子上,\(i\)放在\(j\)上面的必要条件是\(i+j\)是一个完全平方数.问做多能放到几号球. 分析 cogs是简化版,我在网上找了个完整版的测试数据,要求输出方案... 求最大放几号球不方便,我们考虑枚举最大的球号,计算最少需要多少柱子. 我们对于满足\(j<i\)且\(i+j\)是一个完全平方数的\(i,j\),从\(j\)向\(i\)连一条

【水】弱化版魔术球问题

卖个萌 这是一个弱化版的魔术球问题,本来都不好意思丢上来...但是这几天都在看代码没有写东西,还是丢一下凑凑数吧. 不要问我正解哪里进,我也没找到,反正百度魔术球问题第一页都是错的.所有代码都跑不出结果.600这么low的数据没有一个所谓AC代码可以跑的过(似乎我代码加了输出方案也过不去..).所以后面我的数据600就是用没有加输出方案的我的弱弱的程序跑的... 我的代码加了输出方案丢在最后附数据的文章里面了..错的,不过我会尽快改对的..... 魔术球问题弱化版(ball.c/.cpp/.pa

魔术球问题 2011-12-29

算法实现题8-4 魔术球问题(习题 8-14) ´问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,¼的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可放11个球. ´编程任务: 对于给定的n,计算在 n根柱子上最多能放多少个球. ´数据输入: 由文件input.txt提供输入数据.文件第1 行有 1个正整数n,表示柱子数.

【多题合集】网络流24题练习(更新至魔术球问题)

飞行员配对问题(仅求方案总数) 传送门 思路:二分图后dinic走起,各边容量为1 代码: #include<bits/stdc++.h> #define inf 0x7ff using namespace std; int ans,n,n1,s,t,tot=1; int first[105],dis[105],up[105]; bool vis[105]; queue<int>q; struct edge { int u,v,next,w; }e[500]; void add(i

LiberOJ 6003. 「网络流 24 题」魔术球 贪心或者最小路径覆盖

6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有 n nn 根柱子,现要按下述规则在这 n nn 根柱子中依次放入编号为 1,2,3,4,? 1, 2, 3, 4, \cdots1,2,3,4,? 的球. 每次只能在某根柱子的最上面放球. 在同一根柱子中,任何 2 22 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在