魔术球问题

时空限制1000ms / 128MB

题目描述

«问题描述:

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

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

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

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

«编程任务:

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例:

4

输出样例:

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

说明

4<=n<=55


最小路径覆盖问题。

DAG的最小路径覆盖:

定义:在一个有向图中,找出最少的路径,使得这些路径经过了所有的点,且这些路径之间不会经过相同的点。

算法:把原图的每个点V拆成Vx和Vy两个点,如果有一条有向边A->B,那么就加边Ax−>By。这样就得到了一个二分图。那么最小路径覆盖=原图的结点数-新图的最大匹配数。

证明:一开始每个点都是独立的为一条路径,总共有n条不相交路径。我们每次在二分图里找一条匹配边就相当于把两条路径合成了一条路径,也就相当于路径数减少了1。所以找到了几条匹配边,路径数就减少了多少。所以有最小路径覆盖=原图的结点数-新图的最大匹配数。因为路径之间不能有公共点,所以加的边之间也不能有公共点,这就是匹配的定义。

再回来看本题,若两个球编号之和是完全平方数则连边,这样最小路径覆盖数就是柱子数。但是题目给你的是柱子数,要求球数,可以二分球数判断最少需要多少个柱子。

本题的另一个难点是输出每根柱子上球的编号,就是输出最小路径覆盖路径集合的每一条路径上的点。考虑我们是如何求最小路径覆盖的,我们一开始认为路径集合就是点集,然后找到一个匹配边,把这个边的两个点所在的集合合并成一个集合(其实就是把两条路径合并成一条路径)。因为我的最大匹配是用最大流写的,所以最后我判断某两个点是否在一条路径上,就直接判断它们的反向边是否有流量(注意这里的两个点并不是任意的两个点,而是一条路径上相邻的两个点)。

#include<bits/stdc++.h>
#define N 3250
using namespace std;typedef struct
{int v;long long flow;
}ss;
ss edg[N*N];
vector<int>edges[N];
int now_edges=0;
int fl[N][N];void init()
{for(int i=0;i<N;i++)edges[i].clear();now_edges=0;
}void addedge(int u,int v,long long flow)
{fl[u][v]+=flow;edges[u].push_back(now_edges);edg[now_edges++]=(ss){v,flow};edges[v].push_back(now_edges);edg[now_edges++]=(ss){u,0};
}int dis[N],S,T;bool bfs()
{queue<int>q;q.push(S);memset(dis,0,sizeof(dis));dis[S]=1;while(!q.empty()){int now=q.front();q.pop();int Size=edges[now].size();for(int i=0;i<Size;i++){ss e=edg[edges[now][i]];if(e.flow>0&&dis[e.v]==0){dis[e.v]=dis[now]+1;q.push(e.v);}}}if(dis[T]==0)return 0;return 1;
}int current[N];long long dfs(int now,long long maxflow)
{if(now==T)return maxflow;int Size=edges[now].size();for(int i=current[now];i<Size;i++){current[now]=i;ss &e=edg[edges[now][i]];if(e.flow>0&&dis[e.v]==dis[now]+1){long long Flow=dfs(e.v,min(maxflow,e.flow));if(Flow!=0){fl[now][e.v]-=Flow;fl[e.v][now]+=Flow;e.flow-=Flow;edg[edges[now][i]^1].flow+=Flow;return Flow;}}}return 0;
}long long dinic()
{long long ans=0,flow;while(bfs()){memset(current,0,sizeof(current));while(flow=dfs(S,LLONG_MAX/2))ans+=flow;}return ans;
}int f(int n)  //返回球数是n的时候的最小路径覆盖数
{init();S=2*n+1;T=2*n+2;for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++)if((int)sqrt(i+j)*(int)sqrt(i+j)==(i+j))addedge(2*i-1,2*j,1);    addedge(S,2*i-1,1);addedge(2*i,T,1);}return n-dinic();
}int vis[N]={0};void ff(int x,int ans) //dfs寻找每条路径上的点,由于题目的特殊性可以从小到大按顺序寻找
{printf("%d ",x);vis[x]=1;for(int i=x+1;i<=ans;i++)if(fl[i*2][x*2-1]){ff(i,ans);break;}
}int main()
{int n;scanf("%d",&n);int Left=1,Right=1600,ans=1;while(Left<=Right){int mid=(Left+Right)/2;if(f(mid)<=n){ans=mid;Left=mid+1;}else Right=mid-1;}printf("%d\n",ans);for(int i=1;i<=ans;i++){if(!vis[i])ff(i,ans),printf("\n");;}return 0;
}

View Code

转载于:https://www.cnblogs.com/tian-luo/p/9521408.html

网络流24题-魔术球问题相关推荐

  1. 网络流24题 魔术球问题

    传送门 又是一个神奇的建图题,建图\(Van\)♂全不会啊 大体就是我们一个一个的把球放进来,每放进来一个,我们就求出当前的最小路径覆盖数(当前顶点数-最大流),直到最小路径覆盖数\({>}\) ...

  2. 网络流24题——魔术球问题(有向无环图最小路径覆盖)

    链接:https://www.oj.swust.edu.cn/oj/problem/show/1739 分析: 有向无环图最小路径覆盖:给定有向无环图,求一个路径划分,使得每个点在且只在一条路径上,路 ...

  3. [网络流24题]魔术球问题(简化版)

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

  4. 【网络流24题】魔术球问题(最大流)

    [网络流24题]魔术球问题(最大流) 题面 Cogs 题解 是不是像极了最小路径覆盖? 因此,我们枚举放到哪一个球(也可以二分) 然后类似于最小路径覆盖的连边 因为一根柱子对应一个路径的覆盖 所以,提 ...

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

    [题目]#6003. 「网络流 24 题」魔术球 [算法]最小路径覆盖(详细知识参考网络流总结) [题解](i+j)为完全平方数则连边,那么问题转化为添加尽可能多的点使得最小路径覆盖≤n(一条简单路径 ...

  6. 解题报告:线性规划与网络流24题

    目录 A.飞行员配对方案问题 (二分图最大匹配)(最大流)[提高+/省选- ] B.太空飞行计划问题(最大权闭合图转最小割.最小割方案输出)[省选/NOI- ] C.最小路径覆盖问题(有向无环图最小路 ...

  7. 「网络流24题」 题目列表

    「网络流24题」 题目列表 序号 题目标题 模型 题解 1 飞行员配对方案问题 二分图最大匹配 <1> 2 太空飞行计划问题 最大权闭合子图 <2> 3 最小路径覆盖问题 二分 ...

  8. 【算法】【网络流24题】巨坑待填(成功TJ,有时间再填)

    ------------------------------------------------------------------------------------ 17/24 --------- ...

  9. 【题解】网络流24题一句话题解集合

    最近写了下<线性规划与网络流24题>,发下代码和题解,事实上就是将交给cycycy的题解复制一下 T1 飞行员配对方案问题 solution 裸的匈牙利 code #include< ...

最新文章

  1. tomcat启动一直报空指针错误
  2. javacc的源码构建
  3. LeetCode Binary Tree Level Order Traversal
  4. Android中handler的使用及原理---学习笔记
  5. Hadoop Yarn REST API未授权漏洞利用挖矿分析
  6. php 几秒后返回,php计算两个时间差并返回差多少天、时、分、秒
  7. 华为畅享9S曝光:2400万超广角AI三摄+珍珠屏
  8. JavaScript43种常见的浏览器兼容性问题大汇总
  9. 移动健康应用观察:快速问医生的“Web 10年功”
  10. 今天下午又是在教室里坐了一个下午,头有点晕
  11. Qt视频直播软件--项目实战(Day7)
  12. python查火车票_Python实现12306火车票查询系统
  13. Python-opencv学习笔记
  14. 学习笔记:Qt程序打包发布
  15. google多开设置
  16. Python实现图像直方图规定化(直方图匹配)-附完整代码
  17. 数通--交互技术--STP+RSTP详解
  18. MATLAB上的GPU加速计算
  19. Linux下__attribute__((aligned(n)))的使用
  20. oracle19c集群重启,Oracle 19c集群重装

热门文章

  1. 48.结构体位域获取内存模型
  2. Shell脚本笔记(三)shell中的数学计算
  3. Collection集合的三种初始化方法
  4. 对天天开心消消乐(订餐系统)的建议
  5. 安装 SQL Server 2008 R2 的硬件和软件要求(转)
  6. 级联下拉框效果,动态加载图片
  7. ArcGIS.Server.9.3和ArcGIS API for Flex的GeometryService和buffer分析(十)
  8. 对items函数的理解
  9. ROS-3 : Catkin工作空间和ROS功能包
  10. ACM学习历程—UESTC 1226 Huatuo's Medicine(数学)(2015CCPC L)