传送门

%%%KSkun大佬

话说明明是网络流……这题竟然还有打表找规律和纯贪心AC的……都是神犇啊……

来说一下如何建图。首先把每一个点拆成$X_i$和$Y_i$,然后$S$向$X_i$连一条容量为$1$的边,$Y_i$向$T$连一条容量为$1$的边。对于能和它组成完全平方数的点,从$A_j$向$B_i$连一条容量为$1$的边

然后考虑一下,加球不会导致柱子减少,所以可以枚举球数,然后每次加一个球,并跑一次最大流。如果新加入的球是能加到某一个柱子中的,那么这一次跑最大流是能得到新流的,只要能一直得到新流就一直加,当不能的时候,将柱子数加一(即将这一个球放到新的柱子上)

当柱子数等于$n+1$的时候退出,因为第$n+1$根柱子是刚被加的,所以在放最后一个球之前,所有的球都能放在$n$根柱子中,那么当前的球数减一就是答案

然后考虑一下怎么求方案。对于每一个点,我们可以定义$X_i=i*2,Y_i=i*2+1$,那么可以保证任意两个点的$X_i$和$Y_i$不会重复,且不管在哪一个点,除以二之后就是原来的点。那么我们可以在跑$dfs$的时候,把每一个可以往下走增广路的点连边(这就说明他们相加是完全平方数,可以放在同一个柱子里),那么就可以形成一个类似链表的东西。记录一下每一根柱子一开始放的球,然后沿着链表去找这个柱子上有哪些球就可以了

  1. //minamoto
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<queue>
  7. #include<cmath>
  8. using namespace std;
  9. #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
  10. char buf[<<],*p1=buf,*p2=buf;
  11. inline int read(){
  12. #define num ch-'0'
  13. char ch;bool flag=;int res;
  14. while(!isdigit(ch=getc()))
  15. (ch=='-')&&(flag=true);
  16. for(res=num;isdigit(ch=getc());res=res*+num);
  17. (flag)&&(res=-res);
  18. #undef num
  19. return res;
  20. }
  21. char sr[<<],z[];int C=-,Z;
  22. inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
  23. inline void print(int x){
  24. if(C><<)Ot();
  25. while(z[++Z]=x%+,x/=);
  26. while(sr[++C]=z[Z],--Z);
  27. }
  28. const int inf=0x3f3f3f3f,N=,M=;
  29. int head[N],Next[M],ver[M],edge[M],tot=,Pre[N];
  30. inline void add(int u,int v,int e){
  31. ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
  32. ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=;
  33. }
  34. int dep[N],s,t;
  35. int n,m,cnt;
  36. queue<int> q;
  37. bool bfs(){
  38. memset(dep,-,sizeof(dep));
  39. dep[s]=,q.push(s);
  40. while(!q.empty()){
  41. int u=q.front();q.pop();
  42. for(int i=head[u];i;i=Next[i]){
  43. int v=ver[i];
  44. if(dep[v]<&&edge[i])
  45. dep[v]=dep[u]+,q.push(v);
  46. }
  47. }
  48. return ~dep[t];
  49. }
  50. int dfs(int u,int limit){
  51. if(!limit||u==t) return limit;
  52. int flow=,f;
  53. for(int i=head[u];i;i=Next[i]){
  54. int v=ver[i];
  55. if(dep[v]==dep[u]+&&(f=dfs(v,min(limit,edge[i])))){
  56. flow+=f,limit-=f;
  57. edge[i]-=f,edge[i^]+=f;
  58. Pre[u>>]=v>>;
  59. if(!limit) break;
  60. }
  61. }
  62. return flow;
  63. }
  64. int dinic(){
  65. int flow=;
  66. while(bfs()) flow+=dfs(s,inf);
  67. return flow;
  68. }
  69. bool vis[N];int w[];
  70. int main(){
  71. n=read();
  72. s=,t=;
  73. while(m<=n){
  74. ++cnt;
  75. add(s,cnt<<,),add(cnt<<|,t,);
  76. for(int i=sqrt(cnt)+;i*i<(cnt<<);++i) add((i*i-cnt)<<,cnt<<|,);
  77. int s=dinic();
  78. if(!s) w[++m]=cnt;
  79. }
  80. print(--cnt),sr[++C]=;
  81. for(int i=;i<=n;++i){
  82. int u=w[i];
  83. if(!vis[u]){
  84. print(u),sr[++C]=,vis[u]=;
  85. while(Pre[u]&&Pre[u]!=t>>){
  86. u=Pre[u];
  87. vis[u]=;
  88. print(u),sr[++C]=;
  89. }
  90. sr[++C]=;
  91. }
  92. }
  93. Ot();
  94. return ;
  95. }

洛谷P2765 魔术球问题(最大流)的更多相关文章

  1. 洛谷 P2765 魔术球问题 (dinic求最大流,最小边覆盖)

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

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

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

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

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

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

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

  5. 洛谷P2765 魔术球问题

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

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

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

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

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

  8. P2765 魔术球问题

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

  9. [洛谷P3376题解]网络流(最大流)的实现算法讲解与代码

    [洛谷P3376题解]网络流(最大流)的实现算法讲解与代码 更坏的阅读体验 定义 对于给定的一个网络,有向图中每个的边权表示可以通过的最大流量.假设出发点S水流无限大,求水流到终点T后的最大流量. 起 ...

随机推荐

  1. classmethod VS staticmethod

  2. Ubantu下安装adobe flash player插件

    用火狐看视频,要打开Adobe官网下载xxxx,太麻烦. 可以在Terminal下输入: apt-get install flashplugin-nonfree 好了.

  3. 解析Java反射 - invoke方法

    最近工作中涉及到获取同程火车票,大概描述为:将本地获取的发出城市,目的城市及出发时间按固定格式封装,调用接口获取可乘坐座席等级最高的火车票,接口返回数据用包含三层类封装的类接受,接受的类总共为四层,倒 ...

  4. HDU ACM Fibonacci

    Problem Description Fibonacci numbers are well-known as follow: Now given an integer N, please find ...

  5. y3pP5nCr攀科汲野奶园 O8XY02cm脱罕谘诜驮仆补殖沦ltGLD71R

    {字母=2}谘们土毁低聊临禄霉{字母=3}焚派匠莆胺慷{字母=3}孔毡沃卮肪{字母=1}}{字母=1}尚澈心于逃丫导九壮何前僚九粤绦剖逃仲寺椿澈裳枚盟裳鹊酱滥食孤罕胤狼鞘孜跋柿悸菇沽惫菇卮认鹿锤敦擞众 ...

  6. Shell脚本语法---在Makefile等文件…

    1. Shell脚本语法 1.1. 条件测试:test [ 命令test或[可以测试一个条件是否成立,如果测试结果为真,则该命令的Exit Status为0,如果测试结果为假,则命令的Exit Sta ...

  7. Entitlements

    [Entitlements] Entitlements confer specific capabilities or security permissions to your iOS or OS X ...

  8. sql server2008 跨服务器之间复制表数据

    首先2个数据库要能互相访问,在本地数据库用 select * into 新表 from opendatasource('SQLOLEDB','Data Source=远程数据库IP;User ID=用 ...

  9. spring quartz 配置多个定时任务

    1.配置文件-quartz-1.7.3jar   spring版本为3.1.3jar <?xml version="1.0" encoding="UTF-8&quo ...

  10. string基本字符系列容器(二)

    string对象作为vector元素 string对象可以作为vector向量元素,这种用法类似字符串数组. #include<string> #include<vector> ...