【bzoj2229】 Zjoi2011—最小割
http://www.lydsy.com/JudgeOnline/problem.php?id=2229 (题目链接)
题意
给出一张无向图,$q$组询问,每次询问最小割不大于$c$的点对数量。
Solution
orz:DaD3zZ
最小割树什么的好神,但是看不懂啊,不如直接撸代码= =。根据网上神犇的理论,貌似最小割的数目不会超过$n-1$个,所以可以将它构成一棵最小割树。
不过我们的实现并不需要考虑怎么构树。直接暴力的话就是枚举点对,要做$n^2$次$Dinic$,我们通过选择一些优秀的点对来减少$Dinic$的次数。每次分治,任选两个在当前分治区间中的点作为源点和汇点,在原图上做一次$Dinic$,将原图分为了两个割集$S$和$T$,更新$S$和$T$之间的点的最小割。将这两个割集与分治区间取交得到分值区间的割集$S'$和$T'$,然后递归处理$S'$和$T'$就可以了。
值得注意的是,这样子并没有减小问题的规模,只是通过有技巧的选择源点和汇点来减少$Dinic$的次数(虽然我也不知道为什么这样是正确的)。复杂度大概是$O(kn*Dinic)$,$k$这个常数应该不会太大,出题人总不会丧心病狂卡这玩意儿吧,大不了random_shuffle一下= =。
细节
无向图。
代码
// bzoj2229
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf (1ll<<30)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std; const int maxn=200,maxm=10010;
int Q,n,m,cnt,id[maxn],head[maxn],ans[maxn][maxn],vis[maxn],tmp[maxn];
struct edge {int to,next,w;}e[maxm]; namespace Dinic {
int d[maxn],S,T;
void link(int u,int v,int w) {
e[++cnt]=(edge){v,head[u],w};head[u]=cnt;
e[++cnt]=(edge){u,head[v],w};head[v]=cnt;
}
bool bfs() {
memset(d,-1,sizeof(d));
queue<int> q;q.push(S);d[S]=0;
while (!q.empty()) {
int x=q.front();q.pop();
for (int i=head[x];i;i=e[i].next)
if (e[i].w && d[e[i].to]<0) d[e[i].to]=d[x]+1,q.push(e[i].to);
}
return d[T]>0;
}
int dfs(int x,int f) {
if (x==T || f==0) return f;
int w,used=0;
for (int i=head[x];i;i=e[i].next) if (e[i].w && d[e[i].to]==d[x]+1) {
w=dfs(e[i].to,min(e[i].w,f-used));
used+=w,e[i].w-=w,e[i^1].w+=w;
if (used==f) return used;
}
if (!used) d[x]=-1;
return used;
}
int main(int x,int y){
S=x,T=y;int flow=0;
while (bfs()) flow+=dfs(S,inf);
return flow;
}
}
using namespace Dinic; void Init() {
cnt=1;
memset(head,0,sizeof(head));
memset(ans,0x7f,sizeof(ans));
}
void dfs(int x) {
vis[x]=1;
for (int i=head[x];i;i=e[i].next)
if (e[i].w && !vis[e[i].to]) dfs(e[i].to);
}
void solve(int L,int R) {
if (L==R) return;
for (int i=2;i<=cnt;i+=2) e[i].w=e[i^1].w=(e[i].w+e[i^1].w)>>1;
int flow=Dinic::main(id[L],id[R]);
memset(vis,0,sizeof(vis));dfs(id[L]);
for (int i=1;i<=n;i++) {
if (!vis[i]) continue;
for (int j=1;j<=n;j++)
if (!vis[j]) ans[i][j]=ans[j][i]=min(ans[i][j],flow);
}
int l=L,r=R;
for (int i=L;i<=R;i++) vis[id[i]] ? tmp[l++]=id[i] : tmp[r--]=id[i];
for (int i=L;i<=R;i++) id[i]=tmp[i];
solve(L,l-1);solve(r+1,R);
} int main() {
int T;scanf("%d",&T);
while (T--) {
scanf("%d%d",&n,&m);Init();
for (int i=1;i<=n;i++) id[i]=i;
for (int u,v,w,i=1;i<=m;i++) {
scanf("%d%d%d",&u,&v,&w);
Dinic::link(u,v,w);
}
solve(1,n);
scanf("%d",&Q);
for (int c,i=1;i<=Q;i++) {
scanf("%d",&c);int res=0;
for (int j=1;j<=n;j++)
for (int k=j+1;k<=n;k++) if (ans[j][k]<=c) res++;
printf("%d\n",res);
}
puts("");
}
return 0;
}
【bzoj2229】 Zjoi2011—最小割的更多相关文章
- BZOJ2229: [Zjoi2011]最小割
题解: 真是一道神题!!! 大家还是围观JZP的题解吧(网址找不到了...) 代码: #include<cstdio> #include<cstdlib> #include&l ...
- bzoj千题计划139:bzoj2229: [Zjoi2011]最小割
http://www.lydsy.com/JudgeOnline/problem.php?id=2229 最小割树介绍:http://blog.csdn.net/jyxjyx27/article/de ...
- bzoj2229: [Zjoi2011]最小割(分治最小割+最小割树思想)
2229: [Zjoi2011]最小割 题目:传送门 题解: 一道非常好的题目啊!!! 蒟蒻的想法:暴力枚举点对跑最小割记录...绝对爆炸啊.... 开始怀疑是不是题目骗人...难道根本不用网络流?? ...
- [bzoj2229][Zjoi2011]最小割_网络流_最小割树
最小割 bzoj-2229 Zjoi-2011 题目大意:题目链接. 注释:略. 想法: 在这里给出最小割树的定义. 最小割树啊,就是这样一棵树.一个图的最小割树满足这棵树上任意两点之间的最小值就是原 ...
- BZOJ2229—— [Zjoi2011]最小割
0.题目大意:求两点之间的最小割,然后找出其中小于x的数量 1.分析:最小割树水题,上个板子就好 #include <queue> #include <ctime> #incl ...
- BZOJ2229[Zjoi2011]最小割——最小割树
题目描述 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分 ...
- BZOJ2229: [Zjoi2011]最小割(最小割树)
传送门 最小割树 算法 初始时把所有点放在一个集合 从中任选两个点出来跑原图中的最小割 然后按照 \(s\) 集合与 \(t\) 集合的归属把当前集合划分成两个集合,递归处理 这样一共跑了 \(n − ...
- bzoj2229: [Zjoi2011]最小割(最小割树)
传送门 这题是用最小割树做的(不明白最小割树是什么的可以去看看这一题->这里) 有了最小割树就很简单了……点数那么少……每次跑出一个最大流就暴力搞一遍就好了 //minamoto #includ ...
- 【BZOJ2229】[ZJOI2011]最小割(网络流,最小割树)
[BZOJ2229][ZJOI2011]最小割(网络流,最小割树) 题面 BZOJ 洛谷 题解 戳这里 那么实现过程就是任选两点跑最小割更新答案,然后把点集划分为和\(S\)联通以及与\(T\)联通. ...
- 【BZOJ2229】[Zjoi2011]最小割 最小割树
[BZOJ2229][Zjoi2011]最小割 Description 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有 ...
随机推荐
- vue 过滤器基本使用
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化,例如时间戳格式化. 过滤器可以用在: 双花括号插值 v-bind 表达式 (2.1.0+ 开始支持). 过滤器应该被添加在 JavaSc ...
- 谈谈ThreadLocal的设计及不足
用Java语言开发的同学对 ThreadLocal 应该都不会陌生,这个类的使用场景很多,特别是在一些框架中经常用到,比如数据库事务操作,还有MVC框架中数据跨层传递.这里我们简要探讨下 Thread ...
- 浅谈js拖拽
本文来自网易云社区 作者:刘凌阳 前言 本文依据半年前本人的分享<浅谈js拖拽>撰写,算是一篇迟到的文章. 基本思路 虽然现在关于拖拽的组件库到处都是,HTML5也把拖放纳入了标准.但考虑 ...
- item 4: 知道怎么去看推导的类型
本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 对于推导类型结果的查看,根据不同的软件开发阶段,你想知道的信息的不 ...
- ActiveMQ 填坑记
前言 MQ是现在大型系统架构中必不可少的一个重要中间件,之前有偏文章<MQ(消息队列)常见的应用场景解析>介绍过MQ的应用场景,现在流行的几个MQ是rabbitmq,rocketma,ka ...
- Quartz_简单使用
第一步:安装 新建一个QuartzDemo项目后,安装下面的程序包 Install-Package Quartz Install-Package Common.Logging.Log4Net1211 ...
- WordPress更新提示无法创建目录的解决方案
上一篇我们说到无法连接FTP服务器,我们已经完美的解决了,然后...发现...还是无法更新,啥情况??? 提示为无法创建目录 原因是执行更新程序的是www用户, 解决方案如下: 需要把插件或主程序下载 ...
- TRIO-basic变量的状态位
TRIO运动控制器在应用中,我们一般会用一个VR寄存器的状态位来控制一些报警信号,这样有利于代码的优化,同时和触摸屏设置报警信息大大的方便和节约时间. 首先测试了一下一个寄存器可以设置多少个状态位. ...
- LINUX内核分析第七周学习总结——可执行程序的装载
LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...
- JQuery监听页面滚动总结
1.当前滚动的地方的窗口顶端到整个页面顶端的距离: var winPos = $(window).scrollTop(); 2.获取指定元素的页面位置: $(val).offset().top; 3. ...