[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流

Posted wls001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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,? 的球。

  1. 每次只能在某根柱子的最上面放球。
  2. 在同一根柱子中,任何 2 22 个相邻球的编号之和为完全平方数。

试设计一个算法,计算出在 n nn 根柱子上最多能放多少个球。

输入格式

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

输出格式

第一行是球数。接下来的 n nn 行,每行是一根柱子上的球的编号。

样例

样例输入

4

样例输出

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

数据范围与提示

1≤n≤55 1 \leq n \leq 551n55

 

把每个柱子看成一条路径,跑最小路径覆盖。

 

技术分享图片
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 struct data {
 9     int to,next,f;
10 }e[100005];
11 int head[5005],cnt;
12 void add(int u,int v,int f){e[cnt].to=v;e[cnt].next=head[u];e[cnt].f=f;head[u]=cnt++;}
13 int n,m,s,t;
14 bool vis[5005];
15 int q[5005],dis[5005];
16 bool bfs() {
17     memset(dis,-57,sizeof(dis));
18     int h=0,tail=1;
19     q[h]=t;
20     dis[t]=0;
21     while(h!=tail) {
22         int now=q[h++];if(h==5000) h=0;
23         for(int i=head[now];i>=0;i=e[i].next) {
24             if(dis[e[i].to]>-100000||!e[i^1].f) continue;
25             dis[e[i].to]=dis[now]-1;
26             q[tail++]=e[i].to;if(tail==5000) tail=0;
27         }    
28     }
29     return dis[s]>=-100000;
30 }
31 int dfs(int now,int a) {
32     int f=0,flow=0;
33     if(now==t) return a;
34     for(int i=head[now];i>=0;i=e[i].next) {
35         int to=e[i].to;
36         if(dis[to]==dis[now]+1&&e[i].f>0) {
37             f=dfs(to,min(a,e[i].f));
38             flow+=f;
39             e[i].f-=f;
40             e[i^1].f+=f;
41             a-=f;
42             if(a==0) break;
43         }
44     }
45     return flow;
46 }
47 int num=0;
48 int ans=0;
49 int sum=0;
50 int dinic() {
51     while(bfs()) {
52         sum+=dfs(s,2147483647);
53     }
54     return num-sum;
55 }
56 
57 bool work() {
58     num++;
59     add(s,num,1);add(num,s,0);add(num+2500,t,1);add(t,num+2500,0);
60     for(int i=1;i<num;i++) {
61         if(sqrt(i+num)==(int)sqrt(i+num)) add(num,i+2500,1),add(i+2500,num,0);
62     }
63     if(dinic()<=n) return 1;
64     else return 0;
65 }
66 void pout(int x) {
67     vis[x]=1;
68     printf("%d ",x);
69     for(int i=head[x+2500];i>=0;i=e[i].next) {
70         if(e[i].f==1&&!vis[e[i].to]){pout(e[i].to);return;}
71     }
72     return;
73 }
74 int main() {
75     memset(head,-1,sizeof(head));
76     scanf("%d",&n);
77     s=0,t=5001;
78     while(work()) ;
79     num--;
80     printf("%d\n",num);
81     memset(vis,0,sizeof(vis));
82     vis[s]=vis[t]=1;
83     for(int i=1;i<=num;i++) {
84         if(!vis[i]){pout(i);printf("\n");}
85     }
86 }
View Code

 

以上是关于[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流的主要内容,如果未能解决你的问题,请参考以下文章

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

「网络流 24 题」魔术球 的贪心做法和证明

「网络流 24 题」魔术球 的贪心做法和证明

网络流24题魔术球问题(最大流)

网络流24题- 魔术球问题

网络流24题魔术球问题