【洛谷P3329】 [ZJOI2011]最小割(最小割树)
题意:
给出一个无向图,之后有\(q,q\leq 30\)组询问,每组询问有一个\(x\),回答有多少点对\((a,b)\)其\(a-b\)最小割不超过\(x\)。
思路:
这个题做法要最小割树...这个东西大概就是对于当前点集任意选择两个点\(s,t\)作为源点和汇点,然后求出当前最小割,之后两个集合连边为最小割权值;然后两个集合递归下去处理。
显然最后集合中只会存在一个元素,那么最后形成的就是一颗树。
最小割树有一个性质:对于树上\(u,v\)两点,其路径上的边权最小值即为两点的最小割。
这个感谢理解一下?
最后处理的时候每次将点按照集合重排序然后递归下去,另外注意一下更新\(ans\)时的枚举范围,这时两个集合中的任意一对点的最小割都不会超过\(d\)。
直观理解最小割树参见:传送门
代码如下:
/*
* Author: heyuhhh
* Created Time: 2019/10/31 21:20:48
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 155, M = 10005;
#define _S heyuhhh
template <class T>
struct Dinic{
struct Edge{
int v, next;
T flow, w;
Edge(){}
Edge(int v, int next, T flow, T w) : v(v), next(next), flow(flow), w(w) {}
}e[M << 1];
int head[N], tot;
int dep[N];
bool vis[N];
void init() {
memset(head, -1, sizeof(head)); tot = 0;
}
void adde(int u, int v, T w, T rw = 0) {
e[tot] = Edge(v, head[u], w, w);
head[u] = tot++;
e[tot] = Edge(u, head[v], rw, rw);
head[v] = tot++;
}
bool BFS(int _S, int _T) {
memset(dep, 0, sizeof(dep));
queue <int> q; q.push(_S); dep[_S] = 1;
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if(!dep[v] && e[i].flow > 0) {
dep[v] = dep[u] + 1;
q.push(v);
}
}
}
return dep[_T] != 0;
}
T dfs(int _S, int _T, T a) {
T flow = 0, f;
if(_S == _T || a == 0) return a;
for(int i = head[_S]; ~i; i = e[i].next) {
int v = e[i].v;
if(dep[v] != dep[_S] + 1) continue;
f = dfs(v, _T, min(a, e[i].flow));
if(f) {
e[i].flow -= f;
e[i ^ 1].flow += f;
flow += f;
a -= f;
if(a == 0) break;
}
}
if(!flow) dep[_S] = -1;
return flow;
}
T dinic(int _S, int _T) {
T max_flow = 0;
while(BFS(_S, _T)) max_flow += dfs(_S, _T, INF);
return max_flow;
}
void color(int u) {
vis[u] = true;
for(int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if(vis[v] == false && e[i].flow) color(v);
}
}
void pre() {
memset(vis, 0, sizeof(vis));
for(int i = 0; i < tot; i++) e[i].flow = e[i].w;
}
};
Dinic <int> solver;
int n, m;
int c[N][N];
int a[N], ans[N][N];
int tmp1[N], tmp2[N];
void solve(int l, int r) {
if(l >= r) return;
solver.pre();
int S = a[l], T = a[r];
int d = solver.dinic(S, T);
solver.color(S);
for(int i = 1; i <= n; i++) if(solver.vis[i]) {
for(int j = 1; j <= n; j++) if(!solver.vis[j]) {
ans[i][j] = ans[j][i] = min(ans[i][j], d);
}
}
int t1 = 0, t2 = 0;
for(int i = l; i <= r; i++) {
if(solver.vis[a[i]]) tmp1[++t1] = a[i];
else tmp2[++t2] = a[i];
}
for(int i = l; i <= l + t1 - 1; i++) a[i] = tmp1[i - l + 1];
for(int i = l + t1; i <= r; i++) a[i] = tmp2[i - t1 - l + 1];
solve(l, l + t1 - 1); solve(l + t1, r);
}
void run(){
cin >> n >> m;
solver.init();
memset(c, 0, sizeof(c));
memset(ans, INF, sizeof(ans));
for(int i = 1; i <= m; i++) {
int u, v, w; cin >> u >> v >> w;
c[u][v] += w;
c[v][u] = c[u][v];
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(c[i][j]) solver.adde(i, j, c[i][j]);
}
}
for(int i = 1; i <= n; i++) a[i] = i;
solve(1, n);
int q; cin >> q;
for(int k = 1; k <= q; k++) {
int x; cin >> x;
int res = 0;
for(int i = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++)
if(ans[i][j] <= x) ++res;
cout << res << '\n';
}
cout << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
int T; cin >> T;
while(T--) run();
return 0;
}
【洛谷P3329】 [ZJOI2011]最小割(最小割树)的更多相关文章
- 洛谷P3377 【模板】左偏树(可并堆) 题解
作者:zifeiy 标签:左偏树 这篇随笔需要你在之前掌握 堆 和 二叉树 的相关知识点. 堆支持在 \(O(\log n)\) 的时间内进行插入元素.查询最值和删除最值的操作.在这里,如果最值是最小 ...
- 洛谷 P3377 【模板】左偏树(可并堆)
洛谷 P3377 [模板]左偏树(可并堆) 题目描述 如题,一开始有N个小根堆,每个堆包含且仅包含一个数.接下来需要支持两种操作: 操作1: 1 x y 将第x个数和第y个数所在的小根堆合并(若第x或 ...
- bzoj 2039 & 洛谷 P1791 人员雇佣 —— 二元关系最小割
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2039 https://www.luogu.org/problemnew/show/P1791 ...
- 最小表示法模板(洛谷P1368 工艺)(最小表示法)
洛谷题目传送门 最小表示是指一个字符串通过循环位移变换(第一个移到最后一个)所能得到的字典序最小的字符串. 因为是环状的,所以肯定要先转化为序列,把原串倍长. 设决策点为一个表示法的开头.比较两个决策 ...
- 洛谷 P3187 BZOJ 1185 [HNOI2007]最小矩形覆盖 (旋转卡壳)
题目链接: 洛谷 P3187 [HNOI2007]最小矩形覆盖 BZOJ 1185: [HNOI2007]最小矩形覆盖 Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, ...
- LOJ #2185 / 洛谷 P3329 - [SDOI2015]约数个数和(莫比乌斯函数)
LOJ 题面传送门 / 洛谷题面传送门 题意: 求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^md(ij)\),\(d(x)\) 为 \(x\) 的约数个数. \( ...
- 洛谷AT2046 Namori(思维,基环树,树形DP)
洛谷题目传送门 神仙思维题还是要写点东西才好. 树 每次操作把相邻且同色的点反色,直接这样思考会发现状态有很强的后效性,没办法考虑转移. 因为树是二分图,所以我们转化模型:在树的奇数层的所有点上都有一 ...
- ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】
题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
随机推荐
- PHP清除数组中为0的元素
array_diff($arr, [0]): // 清除数组中指定元素 $arr = [1,2,3,0,1]; $arr = array_diff($arr, [0]);//输出[1,2,3,1] v ...
- CodeForces - 1251D (贪心+二分)
题意 https://vjudge.net/problem/CodeForces-1251D 您是一个大型企业的负责人.在您的企业当中共有n位员工为您工作,而且非常有趣的事是这个n是一个奇数(n不能被 ...
- 学习postman教程
postman可以做什么 1.可以做单接口的测试 2.可以调试接口 3.对接口设置变量后,可以做多接口的测试,并输出报告 如何用postman调试接口 1.填写api地址 2.选择请求方式 3.输入a ...
- QT使用LIBS添加绝对路径的dll引用
http://blog.sina.com.cn/s/blog_70b93da90100n6w8.html 参考这篇文章 举例: 要引用 F:\QT\parttime_work\build-JChart ...
- 【未完成】【oracle】单引号使用问题
‘-’不可以用 原因:
- WPF DataGrid 双击行 获得绑定数据
原文:WPF DataGrid 双击行 获得绑定数据 1)增加事件 2)增加对象获取 1)事件代码 Datagrid 增加事件 MouseDoubleClick="dataGrid_Mous ...
- windows golang安装golang.org/x/net text grpc
使用git # 吧$GOPATH替换成自己的GOPATH git clone https://github.com/golang/net.git $GOPATH\src\golang.org\x\ne ...
- CF1244F Chips
题目链接 problem 有一个长度为\(n\)个点连成的环.每个点为黑色或白色.当一个点和与他相邻的两个点颜色不同时.该点的颜色就会改变. 问改变\(K\)次后每个点的颜色. solution 发现 ...
- 【LOJ2402】「THUPC 2017」天天爱射击 / Shooting(整体二分)
点此看题面 大致题意: 有\(n\)个区间,每个区间有一个权值,当权值变成\(0\)时消失.每个时刻将覆盖某一位置的所有区间权值减\(1\),求每个时刻有多少个区间在这一刻消失. 前言 整体二分裸题啊 ...
- Codeforces Round #599 (Div. 1) A. Tile Painting 数论
C. Tile Painting Ujan has been lazy lately, but now has decided to bring his yard to good shape. Fir ...