题面

求所有点对的最小割中<=c的数量

分析

分治最小割板题

首先,注意这样一个事实:如果(X,Y)是某个s1-t1最小割,(Z,W)是某个s2-t2最小割,那么X∩Z、X∩W、Y∩Z、Y∩W这四项不可能均非空。也就是说,最小割不可能相互跨立。

这个蕴含了,最多一共有N-1个不同的s-t最小割。只需把这些割找出来即可。

寻找的方法:首先,在V中任意找两个点a,b,求最大流,把V划分为割X-Y,之后对X、Y分别递归地进行划分。这样就能得到N-1个割了。

(摘自hzwer的博客)

CODE

#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<typename T>inline void read(T &num) {
char ch; int flg=1;
while((ch=getc())<'0'||ch>'9')if(ch=='-')flg=-flg;
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getc());
num*=flg;
}
const int inf = 1e9;
const int MAXN = 155;
const int MAXM = 100005;
int n, m, Q, fir[MAXN], S, T, cnt;
struct edge { int to, nxt, c; }e[MAXM];
inline void add(int u, int v, int cc) { //双向边
e[cnt] = (edge){ v, fir[u], cc }; fir[u] = cnt++;
e[cnt] = (edge){ u, fir[v], cc }; fir[v] = cnt++;
}
int dis[MAXN], vis[MAXN], info[MAXN], cur, q[MAXN];
inline bool bfs() {
int head = 0, tail = 0;
vis[S] = ++cur; q[tail++] = S; dis[S] = 0;
while(head < tail) {
int u = q[head++];
for(int i = fir[u]; ~i; i = e[i].nxt)
if(e[i].c && vis[e[i].to] != cur)
vis[e[i].to] = cur, dis[e[i].to] = dis[u] + 1, q[tail++] = e[i].to;
}
if(vis[T] == cur) memcpy(info, fir, (n+1)<<2);
return vis[T] == cur;
}
int dfs(int u, int Max) {
if(u == T || !Max) return Max;
int flow=0, delta;
for(int i = fir[u]; ~i; i = e[i].nxt)
if(e[i].c && dis[e[i].to] == dis[u] + 1 && (delta=dfs(e[i].to, min(e[i].c, Max-flow)))) {
e[i].c -= delta, e[i^1].c += delta, flow += delta;
if(flow == Max) return flow;
}
if(!flow) dis[u] = -1;
return flow;
}
inline int dinic() {
int flow=0, x;
while(bfs()) while((x=dfs(S, inf))) flow+=x;
return flow;
}
inline void clear() {
for(int i = 0; i < cnt; i+=2)
e[i].c = e[i^1].c = (e[i].c + e[i^1].c) >> 1;
}
int now; bool mark[MAXN];
void cut(int u) {
mark[u] = 1;
for(int i = fir[u]; ~i; i = e[i].nxt)
if(e[i].c && !mark[e[i].to]) cut(e[i].to);
}
int a[MAXN], tmp[MAXN], ans[MAXN][MAXN];
void solve(int l, int r) {
if(l == r) return; clear();
S = a[l], T = a[r]; int MinCut = dinic();
memset(mark, 0, sizeof mark); cut(S);
for(int i = 1; i <= n; ++i) if(mark[i])
for(int j = 1; j <= n; ++j) if(!mark[j])
ans[i][j] = ans[j][i] = min(ans[i][j], MinCut);
int L = l, R = r;
for(int i = l; i <= r; ++i)
if(mark[a[i]]) tmp[L++] = a[i];
else tmp[R--] = a[i];
for(int i = l; i <= r; ++i) a[i] = tmp[i];
solve(l, L-1), solve(R+1, r);
}
int arr[12000], top;
int main () {
int kase, x;
read(kase);
while(kase--) {
memset(fir, -1, sizeof fir); cnt = 0;
memset(ans, 0x7f, sizeof ans);
read(n), read(m);
for(int i = 1, x, y, z; i <= m; ++i)
read(x), read(y), read(z), add(x, y, z);
for(int i = 1; i <= n; ++i) a[i] = i;
solve(1, n);
top = 0;
for(int i = 1; i <= n; ++i)
for(int j = i+1; j <= n; ++j)
arr[top++] = ans[i][j];
sort(arr, arr+top);
read(Q);
while(Q--)
read(x), printf("%d\n", upper_bound(arr, arr+top, x)-arr);
puts("");
}
}

BZOJ 2229 / Luogu P3329 [ZJOI2011]最小割 (分治最小割板题)的更多相关文章

  1. bzoj2229: [Zjoi2011]最小割(分治最小割+最小割树思想)

    2229: [Zjoi2011]最小割 题目:传送门 题解: 一道非常好的题目啊!!! 蒟蒻的想法:暴力枚举点对跑最小割记录...绝对爆炸啊.... 开始怀疑是不是题目骗人...难道根本不用网络流?? ...

  2. 最小割分治(最小割树):BZOJ2229 && BZOJ4519

    定理:n个点的无向图的最小割最多n-1个. 可能从某种形式上形成了一棵树,不是很清楚. 最小割分治:先任选两个点求一边最小割,然后将两边分别递归,就能找到所有的最小割. 这两个题是一样的,直接搬din ...

  3. 【bzoj4519】[Cqoi2016]不同的最小割 分治+最小割

    题目描述 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割.对于带权图来说,将所有顶点处在不同 ...

  4. [ZJOI2011]最小割 & [CQOI2016]不同的最小割 分治求最小割

    题面: [ZJOI2011]最小割 [CQOI2016]不同的最小割 题解: 其实这两道是同一道题.... 最小割是用的dinic,不同的最小割是用的isap 其实都是分治求最小割 简单讲讲思路吧 就 ...

  5. ZJOI 最小割 CQOI 不同的最小割 (最小割分治)

    题目1 ZJOI 最小割 题目大意: 求一个无向带权图两点间的最小割,询问小于等于c的点对有多少. 算法讨论: 最小割 分治 代码: #include <cstdlib> #include ...

  6. POJ3308 Paratroopers(最小割/二分图最小点权覆盖)

    把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运 ...

  7. BZOJ_1797_[Ahoi2009]Mincut 最小割_最小割+tarjan

    BZOJ_1797_[Ahoi2009]Mincut 最小割_最小割+tarjan Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤ ...

  8. ZOJ 3792 Romantic Value 最小割(最小费用下最小边数)

    求最小割及最小花费 把边权c = c*10000+1 然后跑一个最小割,则flow / 10000就是费用 flow%10000就是边数. 且是边数最少的情况.. #include<stdio. ...

  9. 【bzoj2229】[Zjoi2011]最小割 分治+网络流最小割

    题目描述 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分 ...

随机推荐

  1. # VsCode 配置C++调试运行

    VsCode 配置C++调试运行 打开命令面板快捷键为F1,软件上写的Ctrl+Shift+P似乎没用 先安装插件使得可以运行 先自行在vsc扩展中搜索C++安装C/C++插件 再参考知乎专栏中安装c ...

  2. Python面试题集合带答案

    目录 Python基础篇 1:为什么学习Python 2:通过什么途径学习Python 3:谈谈对Python和其他语言的区别 Python的优势: 4:简述解释型和编译型编程语言 5:Python的 ...

  3. Linux下如何查看tomcat是否启动、查看tomcat启动日志

    在Linux系统下,重启Tomcat使用命令的操作! 1.首先,进入Tomcat下的bin目录 cd /usr/local/tomcat/bin 使用Tomcat关闭命令 ./shutdown.sh ...

  4. MySQL存储的字段是不区分大小写的,你知道吗?

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 00 简单回顾 之前写过一篇关于mysql 对表大小写敏感的问题,其实在mysql中字段存储的内容是不区分大小写的,本篇进 ...

  5. opencv-02--图像的邻域操作

    图像的邻域操作 很多时候,我们对图像处理时,要考虑它的邻域,比如3*3是我们常用的,这在图像滤波.去噪中最为常见,下面我们介绍如果在一次图像遍历过程中进行邻域的运算. 下面我们进行一个简单的滤波操作, ...

  6. centos源码安装nginx

    1.安装依赖 nginx对以下工具包有依赖,我们可以一键安装,命令: yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-dev ...

  7. Rsync同步过程中遇到的常见问题

    一.Rsync服务介绍 Rsync属于一款实现全量及增量同步数据的软件工具,适用于unix/linux/windows等多种操作系统平台. Rsync软件能实现本地复制,远程复制,或者远程守护进程方式 ...

  8. Servlet实现图片读取显示

    1.导入jar包:commons-io-1.4.jar 2.index.jsp: <%@ page language="java" import="java.uti ...

  9. PHP常见算法

    算法的概念:解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作.一个问题可以有多种算法,每种算法都不同的效率.一个算法具有的特征:有穷,确切,输入,输出,可行 ...

  10. APP漏洞之WebView File域同源策略绕过漏洞

    i春秋作家:MAX丶 基本知识Android架构 Kernel内核层 漏洞危害极大,通用性强 驱动由于多而杂,也可能存在不少漏洞 Libaries系统运行库层 系统中间件形式提供的运行库 包括libc ...