【网络流24题】魔术球问题(最小不相交路径覆盖)

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

2014年3月7日3,5344

Description

假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,4的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。

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

Input Format

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

Output Format

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

Sample Inpu

4

Sample Output

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

题解:这道题就是小的必须在大的下面,所以保证了DAG的性质。

如果a,b(a<b)并且a+b是一个平方数。

那么a-->b连一条边,那么问题是不是转化为,一个DAG最少需要多少条路径(不想交),可以

完全覆盖,如果超过了n则不行。

所以维护一下网络流,codevs上没开spj,路径方面处理一下。

  1 #include<cstring>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<cstdio>
  5 #include<iostream>
  6 #include<queue>
  7
  8 #define N 10007
  9 #define M 200007
 10 #define INF 1000000007
 11 using namespace std;
 12 inline int read()
 13 {
 14     int x=0,f=1;char ch=getchar();
 15     while(ch<‘0‘||ch>‘9‘){if (ch==‘-‘)f=-1;ch=getchar();}
 16     while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
 17     return x*f;
 18 }
 19
 20 int n,S,T,ans,s;
 21 int cnt=1,head[N],rea[M],val[M],next[M];
 22 int dis[N],to[N],flag[N];
 23
 24 void add(int u,int v,int fee)
 25 {
 26     next[++cnt]=head[u];
 27     head[u]=cnt;
 28     rea[cnt]=v;
 29     val[cnt]=fee;
 30 }
 31 bool bfs()
 32 {
 33     for (int i=1;i<=T;i++)dis[i]=0;
 34     dis[S]=1;queue<int>q;q.push(S);
 35     while(!q.empty())
 36     {
 37         int u=q.front();q.pop();
 38         for (int i=head[u];i!=-1;i=next[i])
 39         {
 40             int v=rea[i],fee=val[i];
 41             if (!dis[v]&&fee>0)
 42             {
 43                 dis[v]=dis[u]+1;
 44                 if (v==T) return 1;
 45                 q.push(v);
 46             }
 47         }
 48     }
 49     return 0;
 50 }
 51 int dfs(int u,int MF)
 52 {
 53     int res=0;
 54     if (u==T||MF==0) return MF;
 55     for (int i=head[u];i!=-1;i=next[i])
 56     {
 57         int v=rea[i],fee=val[i];
 58         if (dis[v]!=dis[u]+1) continue;
 59         int x=dfs(v,min(MF,fee));
 60         if (x)
 61         {
 62             val[i]-=x,val[i^1]+=x;
 63             MF-=x,res+=x;
 64             if (MF==0) return res;
 65         }
 66     }
 67     if (!res) dis[u]=0;
 68     return res;
 69 }
 70 void Dinic()
 71 {
 72     int res=0;
 73     while(bfs())
 74     {
 75         int x=dfs(S,INF);
 76         while(x)
 77         {
 78             res+=x;
 79             x=dfs(S,INF);
 80         }
 81     }
 82     ans-=res;
 83 }
 84 int main()
 85 {
 86     memset(head,-1,sizeof(head));
 87     n=read();
 88     S=0,T=10001;
 89     while(true)
 90     {
 91         ans++,s++;
 92         for (int i=1;i<s;i++)
 93             if (sqrt(i+s)==(int)(sqrt(i+s))) add(i,s+5000,1),add(s+5000,i,0);
 94         add(S,s,1),add(s,S,0),add(s+5000,T,1),add(T,s+5000,0);
 95         Dinic();
 96         if (ans>n) break;
 97     }
 98     printf("%d\n",s-1);
 99     for (int i=1;i<s;i++)
100         for (int j=head[i];j!=-1;j=next[j])
101         {
102             int v=rea[j],fee=val[j];
103             if (!fee) {to[i]=v-5000;break;}
104         }
105     for (int i=1;i<s;i++)
106     {
107         if (flag[i]) continue;
108         int t=i;
109         while(t!=-5000)
110         {
111             flag[t]=1;
112             printf("%d ",t);
113             t=to[t];
114         }
115         printf("\n");
116     }//十分巧妙的构思,转化问题十分优秀。
117 }
时间: 2024-11-05 15:56:15

【网络流24题】魔术球问题(最小不相交路径覆盖)的相关文章

「Luogu2765」[网络流24题] 魔术球问题

->戳我进原题 [网络流24题] 魔术球问题 时空限制:1000ms / 128MB 问题描述 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可放11 个球. 编程任务 对于给定的n,计算在n根柱子上最多能放多少个球. 输入格式 第1 行有1个正整数n,表示柱子数. 输出格式 程序运

[网络流24题]魔术球问题

问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可放11个球. ´编程任务: 对于给定的n,计算在 n根柱子上最多能放多少个球. ´数据输入: 文件第1 行有 1个正整数n,表示柱子数. ´结果输出: 文件的第一行是球数. 数据规模 n<=60  保证答案小于16

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

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

LiberOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

#6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 G 公司有 n nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n nn 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入格式 文件的第 1 11 行中有 1 11 个正整数 n nn,表示有 n nn 个仓库.第 2 22 行中有 n nn 个

[luoguP2765] 魔术球问题(最大流—最小不相交路径覆盖)

传送门 枚举球的个数 num 如果 i < j && (i + j) 是完全平方数,那么 i -> j' 连一条边 再加一个超级源点 s,s -> i 再加一个超级汇点 t,i' -> t 那么当前可以放的柱子的最小数量就是最小不相交路径数 如果当前的最小不相交路径数 > num,break 求最大流的时候别忘了记录方案 ——代码 1 #include <cmath> 2 #include <queue> 3 #include <

BZOJ 1221 HNOI 2001 软件开发/网络流24题 餐巾计划问题 最小费用最大流

题目大意:有一个软件公司,每天需要给一些员工准备消毒毛巾,这些毛巾可以循环利用,但是需要消毒.可以将毛巾送去消毒,有两种方式,A天fA花费,B天fB花费.或者还可以直接买新毛巾,问为了满足员工的需求,至少需要花多少钱. 思路:经典的费用流问题.将每一天拆点,S向每一天<<1连边,约束每一天需要多少毛巾:每一天<<1|1向T连边,约束每一天需要的毛巾.每一天<<1向这一天清洗的毛巾能够使用的那一天<<1|1,注意A和B.毛巾可以延后使用,那么每一天<&l

网络流24题之最小路径覆盖问题

DAG的最小不相交路径覆盖 算法:把原图的每个点V拆成Vx 和Vy两个点,如果有一条有向边A->B,那么就加边Ax−>By .这样就得到了一个二分图.那么最小路径覆盖=原图的结点数-新图的最大匹配数. 证明:一开始每个点都是独立的为一条路径,总共有n条不相交路径.我们每次在二分图里找一条匹配边就相当于把两条路径合成了一条路径,也就相当于路径数减少了1.所以找到了几条匹配边,路径数就减少了多少.所以有最小路径覆盖=原图的结点数-新图的最大匹配数. 因为路径之间不能有公共点,所以加的边之间也不能有

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 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在 

[loj #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 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在