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

  题目链接

  这题……讲道理我没看懂。

  不过我看懂题解的代码是在干嘛了qwq

  题解是zhaoyifan的题解

  然后……我来讲讲这个题解好了。

  题解把值为i的球拆成了两个,一个编号是i*2,一个编号是i*2+1。 

  为什么编号要这么编呢?因为统计编号的时候好统计qwq 

  然后从起点向i*2连一条边,从i*2+1到终点连一条边。

  然后对于能够跟他凑成完全平方数的连边。

  然后跑最大流,如果发现这个球不能串进原来的柱子上,也就是说最大流没有变化,那么就新加一条柱子。

  当柱子数超过n的时候就退出循环开始统计。

  大概……是这样。

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<cmath>
#define maxn 200020
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch==‘-‘)    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-‘0‘;
        ch=getchar();
    }
    return num*f;
}

bool calc(int x){    return sqrt(x)*sqrt(x)==x;    }

inline int count(int i){    return i&1?i+1:i-1;    }

struct Edge{
    int next,to,val;
}edge[maxn*5];
int head[maxn],num;
inline void addedge(int from,int to,int val){
    edge[++num]=(Edge){head[from],to,val};
    head[from]=num;
}
inline void add(int from,int to,int val){
    addedge(from,to,val);
    addedge(to,from,0);
}

bool vis[maxn];
int dfn[maxn];
int list[maxn];
int road[maxn];
int Start,End;

bool bfs(){
    memset(vis,0,sizeof(vis));
    queue<int>q;    q.push(Start);
    vis[Start]=1;    dfn[Start]=1;
    while(!q.empty()){
        int from=q.front();    q.pop();
        for(int i=head[from];i;i=edge[i].next){
            int to=edge[i].to;
            if(vis[to]||edge[i].val==0)    continue;
            vis[to]=1;    q.push(to);
            dfn[to]=dfn[from]+1;
        }
    }
    return vis[End];
}

int dfs(int x,int val){
    if(x==End||val==0)    return val;
    int flow=0;    vis[x]=1;
    for(int &i=list[x];i;i=edge[i].next){
        int to=edge[i].to;
        if(vis[to]||edge[i].val==0||dfn[to]!=dfn[x]+1)    continue;
        int now=dfs(to,min(val,edge[i].val));
        edge[i].val-=now;    edge[count(i)].val+=now;    flow+=now;    val-=now;
        road[x>>1]=to>>1;
        if(val<=0)    break;
    }
    if(flow!=val)    dfn[x]=-1;
    return flow;
}

int maxflow(){
    int ans=0;
    while(bfs()){
        memset(vis,0,sizeof(vis));
        for(int i=Start;i<=End;++i)    list[i]=head[i];
        int now=dfs(Start,0x7fffffff);
        if(!now)    break;
        ans+=now;
    }
    return ans;
}

int tot;
int cnt;
int New[maxn];

int main(){
    End=50003;
    int n=read();
    while(tot<=n){
        cnt++;    add(Start,cnt*2,1);    add(cnt*2+1,End,1);
        for(int i=sqrt(cnt)+1;i*i<cnt*2;++i)
            add((i*i-cnt)*2,cnt*2+1,1);
        int ans=maxflow();
        if(ans==0)    New[++tot]=cnt;
    }
    printf("%d\n",--cnt);
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;++i){
        if(vis[New[i]])    continue;
        int x=New[i];    vis[x]=1;
        while((x!=End>>1)&&x){
            printf("%d ",x);
            x=road[x];
            vis[x]=1;
        }
        printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/cellular-automaton/p/8206506.html

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

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

面试之加分项vue(没看懂,。。。。)

对大部分人来说,掌握Vue.js基本的几个API后就已经能够正常地开发前端网站.但如果你想更加高效地使用Vue来开发,成为Vue.js大师,那下面我要传授的这五招你一定得认真学习一下了.在面试过程很多HR会问到. 第一招:化繁为简的Watch 场景还原: 组件创建的时候我们获取一次列表,同时监听input框,每当发生变化的时候重新获取一次筛选后的列表这个场景很常见,有没有办法优化一下呢? 招式解析: 首先,在watch中,可以直接使用函数的字面量名称:其次,声明immediate:true表示创

poj 1502 MPI Maelstrom Dijkstra算法的简单运用 ,呵呵,,我估计有很多人都没看懂什么意思,我也看了很久

MPI Maelstrom Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5831   Accepted: 3621 Description BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed shared memory machine with a hierarchic

QT插件开发方式(没看懂)

创建一个QT的库项目,删除自动生成的.h和.cpp文件,添加一个接口定义.h文件和一个接口实现类(一个.h一个.cpp).代码如下: 1.接口文件源码 #ifndef PLUGININTERFACE_H#define PLUGININTERFACE_H #include <QString> class EchoInterface{public: virtual ~EchoInterface() {} virtual QString echo(const QString &message

关于this的例子解说:引用高级程序第三版中的代码 this在ECMA中介绍的比较复杂。很多我都没看懂。

想要了解THIs的值如何变化的要了解很多知识点.这里我就简单点介绍下this的值如何变化的. 10.1.6 活动对象 当控制进入函数代码的执行上下文时,创建一个活动对象并将它与该执行上下文相关联, 并使用一个名为 arguments.特征为 { DontDelete } 的属性初始化该对象.该属性的初始值是 稍后将要描述的一个参数对象. 接下来,这个活动对象将被用作变量初始化的可变对象. 活动对象纯粹是一种规范性机制,在 ECMAScript 访问它是不可能的.只能访问其成员而 非该活动对象本身

P2765 魔术球问题

这道题目,一眼看上去,并不能用网络流做 但是我们发现,如果将每个点拆成x和x' 然后x连源点,x'连汇点 都用容量为一的边 再然后是找这个数可以与那个数组成完全平方数,然后将这个数i与x'连边 每加入一个点就跑一次最大流 那么如果可以塞进原柱,那么最大流就得到1否则为0 那么我们在得到0的时候新建柱子即可 另外,我们要注意 在判断完全平方数的时候 sqrt(ge+i)*sqrt(ge+i)==ge+i 这样判断在Windows下是正确的 但在Linux下要写成(int)sqrt(ge+i)*sq

只有我一个能看懂的乱乱的函数基础知识复习

首先函数是什么呢????函数封装了一个功能,需要的时候就去调用就好,def ret_demo(dic):#1.先定义一个函数 while True:#3.开始执行while循环 if len(dic) > 3:#4.判断长度是否大于三, print("长度超了") return False#5.返回一个 False,return是结束标志 break #return后面的不执行 else: print('长度刚刚好') ret = ret_demo([1,2,3,4,5])#2.

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

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

《大话西游》20年后重映(附影评:《大话西游》你真的看懂了吗?)

2014-10-25 02:43:24 来源: 北京日报(北京) 本报讯 (记者 周南焱)"电影里的台词差点儿都能背,但在影院里再看还是会笑.看到最后紫霞仙子死的时候.还是忍不住落泪! "昨天下午,经典老片<大话西游>在海航活力天宝影城又一次上映,一位重温影片的观众如是说.还有观众反映,用如今的电影技术水准来看,<大话西游>确实有点老土,但从内容来看还是那么亲切. 周星驰主演的<大话西游>20年前公映,当时票房大败. 但谁也没想到,该片通过盗版光碟和

网络流24题——魔术球问题 luogu 2765

题目描述:这里 这道题是网络流问题中第一个难点,也是一个很重要的问题 如果直接建图感觉无从下手,因为如果不知道放几个球我就无法得知该如何建图(这是很显然的,比如我知道$1+48=49=7^2$,可是我都不知道是否能放到第48个球,那我怎么知道如何建边呢?) 所以这时就体现出了一个很重要的想法:枚举答案!!! 我们知道,正常有二分答案的做法,可以二分一个答案然后检验 这里用类似的想法,但由于答案比较小而且建图更方便,所以我们直接从小往大枚举答案即可 之所以建图更方便,是因为如果我们从小向大枚举答案