https://www.luogu.org/problemnew/show/P2765

看到这一题第一眼想到:这不是二分最大流吗,后来发现还有一种更快的方法。

首先如果知道要放多少个球求最少的柱子,很显然是一道最小点路径覆盖的题,将一个点拆成u,v两个点,u和S相连,v和T相连,之后的有向边i,就用ui和vj相连即可。

但是这题首先不知道有多少个球,所以考虑依次加入点以及和这个点相关的边,然后在残余网络上跑新的最大流,如果可以跑出流量来意味着这个点成功在现有的柱子上按排上了,如果跑不出来说明按排不上,需要重新开一根柱子放这个点。

直到跑到答案k的时候,柱子数超过了n,要的答案就是k - 1,至于方案,只要在最后的残余网络图上面搜索一下每个点的前驱即可。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = ;
const int maxm = ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
int a[maxn];
struct Edge{
int to,next,cap,flow;
Edge(){}
Edge(int to,int next,int cap,int flow):to(to),next(next),cap(cap),flow(flow){}
}edge[maxm * ];
int head[maxn * ],dis[maxn * ],pre[maxn * ],nxt[maxn * ],vis[maxn * ];
int n,s,tot,t;
void init(int N,int S,int T){
n = N;s = S;t = T;
for(int i = ; i <= n ; i ++) head[i] = -;
tot = ;
}
void add(int u,int v,int w){
edge[tot] = Edge(v,head[u],w,);
head[u] = tot++;
edge[tot] = Edge(u,head[v],,);
head[v] = tot++;
}
bool BFS(){
for(int i = ; i <= n; i ++) dis[i] = -;
queue<int>Q;
dis[s] = ; Q.push(s);
while(!Q.empty()){
int u = Q.front(); Q.pop();
for(int i = head[u]; ~i ; i = edge[i].next){
int v = edge[i].to;
if(~dis[v] || edge[i].cap <= edge[i].flow) continue;
dis[v] = dis[u] + ;
Q.push(v);
}
}
return ~dis[t];
}
int dfs(int u,int a){
if(u == t || !a) return a;
int flow = ;
for(int &i = pre[u]; ~i ; i = edge[i].next){
int v = edge[i].to;
if(dis[u] + != dis[v]) continue;
int f = dfs(v,min(a,edge[i].cap - edge[i].flow));
if(!f) continue;
a -= f; flow += f;
edge[i].flow += f;
edge[i ^ ].flow -= f;
}
return flow;
}
int maxflow(){
int flow = ;
while(BFS()){
for(int i = ; i <= n ; i ++) pre[i] = head[i];
flow += dfs(s,INF);
}
return flow;
}
void search(int t){
for(int i = ; i <= t; i ++){
for(int j = head[i]; ~j ; j = edge[j].next){
int v = edge[j].to;
if(v == s) continue;
if(edge[j].flow){
nxt[i] = v - maxn;
vis[v - maxn] = ;
}
}
}
for(int i = ; i <= t; i ++){
if(!vis[i]){
for(int j = i; j; j = nxt[j]){
printf("%d ",j);
}
puts("");
}
}
}
int main(){
Sca(N);
for(int i = ; i <= ; i ++) a[i] = i * i;
int S = ,T = ;
init(,S,T);
int num = ,k;
int cnt = ;
for(k = ;num <= N; k ++){
while(k + k > a[cnt + ]) cnt++;
add(S,k,);
add(k + maxn,T,);
for(int i = cnt ; i >= ; i --){
if(a[i] - k <= ) break;
add(a[i] - k,k + maxn,);
}
if(!maxflow()) num++;
}
k-=; num--;
Pri(k);
search(k);
return ;
}

洛谷P2765魔术球问题 最小路径覆盖的更多相关文章

  1. luogu P2765 魔术球问题 (最小路径覆盖)

    大意:给定n根柱子, 依次放入1,2,3,...的球, 同一根柱子相邻两个球和为完全平方数, 求最多放多少个球. 对和为平方数的点连边, 就相当于求DAG上最小路径覆盖. #include <i ...

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

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

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

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

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

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

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

    #6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 ...

  6. 洛谷P2765 魔术球问题(最大流)

    传送门 %%%KSkun大佬 话说明明是网络流……这题竟然还有打表找规律和纯贪心AC的……都是神犇啊…… 来说一下如何建图.首先把每一个点拆成$X_i$和$Y_i$,然后$S$向$X_i$连一条容量为 ...

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

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

  8. 洛谷P2765 魔术球问题

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

  9. 洛谷 P3187 BZOJ 1185 [HNOI2007]最小矩形覆盖 (旋转卡壳)

    题目链接: 洛谷 P3187 [HNOI2007]最小矩形覆盖 BZOJ 1185: [HNOI2007]最小矩形覆盖 Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, ...

随机推荐

  1. xml模块 增删改查

    import xml.etree.ElementTree as ET tree = ET.parse("xml test") #open root = tree.getroot() ...

  2. 【python练习题】程序13

    #题目:打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身.例如:153是一个"水仙花数",因为153= ...

  3. git使用常见问题

    1.git branch使用,创建新的分之后做修改后,其他分支也被同步修改 问题: 原项目在 master 分支,执行下面的操作:  git branch test  git checkout tes ...

  4. 【嵌入式】Arduino编程基础到应用全解析

    Arduino Author: Andrew.Du 基础 基础语法: setup() loop() pinMode(引脚,模式) pinMode(13,OUTPUT):设置13号引脚为输出 //在使用 ...

  5. C++:如何正确的定义一个接口类

    C++中如何定义接口类?首先给接口类下了定义:接口类应该是只提供方法声明,而自身不提供方法定义的抽象类.接口类自身不能实例化,接口类的方法定义/实现只能由接口类的子类来完成. 而对于C++,其接口类一 ...

  6. M3U8文件

    M3U本质上说不是音频文件,它是音频文件的列表文件,是纯文本文件.你下载下来打开它,播放软件并不是播放它,而是根据它的记录找到网络地址进行在线播放. M3U文件的大小很小,也就是因为它里面没有任何音频 ...

  7. linux目录文件及系统启动知识

    一.Linux系统目录结构介绍 1.Linux 与 Windows目录结构对比 Linux与Windows的目录结构对比见下图. Linux 目录特点: /etc/hosts      /root/d ...

  8. P1567 气温统计

    P1567 题目描述 炎热的夏日,KC 非常的不爽.他宁可忍受北极的寒冷,也不愿忍受厦门的夏天.最近,他开始研究天气的变化.他希望用研究的结果预测未来的天气. 经历千辛万苦,他收集了连续 N(1≤N≤ ...

  9. Appium+python+html生成饼图测试报告

    历时三周这个小框架终于正式运行了,git源码地址;https://github.com/jiyanjiao/AutoTEST/tree/master/qingqi_driver_app 报告如图:

  10. VS编译LESS插件

    1. LESS   用LESS写CSS可以用写程序代码的习惯写CSS.用了之后写CSS的效率会提高很多. 2.解释LESS 写出来的文件扩展名是.less,要运行的话,先解释成正常的CSS文件. 3. ...