题面

求所有点对的最小割中<=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. [转帖]ASP.NET Core 中间件(Middleware)详解

    ASP.NET Core 中间件(Middleware)详解   本文为官方文档译文,官方文档现已非机器翻译 https://docs.microsoft.com/zh-cn/aspnet/core/ ...

  2. 关于NumPy中数组轴的理解

    参考原文链接(英文版):https://www.sharpsightlabs.com/blog/numpy-axes-explained/:中文版:https://www.jianshu.com/p/ ...

  3. PHP的 parse_ini_file 解析配置文件

    解析配置文件: parse_ini_file 类似解析php.ini文件样 配置文件内容如下: Example #1 sample.ini 的内容 ; This is a sample configu ...

  4. SAS学习笔记21 散点图、条形图

  5. MongoDB增删改

    一.数据库操作 显示现有的数据库,命令:show dbs 或者 databases; 示当前使用的数据库,命令:db 切换当前使用的数据库,命令:use 数据库名称 删除数据库,命令:db.dropD ...

  6. zblog2.X 连不上数据库原因

    数据库配置Dim ZC_MSSQL_DATABASEZC_MSSQL_DATABASE="zb20" Dim ZC_MSSQL_USERNAMEZC_MSSQL_USERNAME= ...

  7. c# 163网易发送邮件

    是4.0的,说以添加包是 代码: public class SendEmailInfo { /// <summary> /// 发送邮件 /// </summary> /// ...

  8. Python练习_文件操作_day8

    1. 1.作业 1,有如下文件,a1.txt,里面的内容为: 老男孩是最好的学校, 全心全意为学生服务, 只为学生未来,不为牟利. 我说的都是真的.哈哈 分别完成以下的功能: a,将原文件全部读出来并 ...

  9. GraphQL实战篇(一)

    看过基础篇的都知道,GraphQL创建Schema有两种方式,Schema First和Graph Type,前者使用GraphQL Schema Language类似于EF的DB First:后者和 ...

  10. 借助Spring工具类如何实现支持数据嵌套的赋值操作

    假设有两个Bean A和B,想将B中的属性赋值到A实体中,可以使用get set来实现,当属性过多时,就会显得很冗余,可以使用spring提供的BeanUtils.copyProperties()来实 ...