bzoj 2229 [Zjoi2011]最小割(分治+最小割)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=2229
【题意】
回答若干个关于割不超过x的点对数目的询问。
【思路】
[最小割最多有n-1个,这n-1个最小割构成一个最小割树]
分治法寻找n-1个最小割。对于当前点集X,任选两点为ST做最小割,然后找出与S相连的所有点和与T相连的所有点构成S集与T集,更新S集与T集的最小割。然后递归处理两个集合。
【代码】
- #include<set>
- #include<cmath>
- #include<queue>
- #include<vector>
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
- #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
- using namespace std;
- typedef long long ll;
- const int N = 2e3+;
- const int inf = 1e9;
- ll read() {
- char c=getchar();
- ll f=,x=;
- while(!isdigit(c)) {
- if(c=='-') f=-; c=getchar();
- }
- while(isdigit(c))
- x=x*+c-'',c=getchar();
- return x*f;
- }
- struct Edge {
- int u,v,cap,flow;
- };
- struct Dinic {
- int n,m,s,t;
- int d[N],cur[N],vis[N];
- vector<int> g[N];
- vector<Edge> es;
- queue<int> q;
- void init(int n) {
- this->n=n;
- es.clear();
- FOR(i,,n) g[i].clear();
- }
- void clear() {
- FOR(i,,(int)es.size()-) es[i].flow=;
- }
- void AddEdge(int u,int v,int w) {
- es.push_back((Edge){u,v,w,});
- es.push_back((Edge){v,u,,});
- m=es.size();
- g[u].push_back(m-);
- g[v].push_back(m-);
- }
- int bfs() {
- memset(vis,,sizeof(vis));
- q.push(s); d[s]=; vis[s]=;
- while(!q.empty()) {
- int u=q.front(); q.pop();
- FOR(i,,(int)g[u].size()-) {
- Edge& e=es[g[u][i]];
- int v=e.v;
- if(!vis[v]&&e.cap>e.flow) {
- vis[v]=;
- d[v]=d[u]+;
- q.push(v);
- }
- }
- }
- return vis[t];
- }
- int dfs(int u,int a) {
- if(u==t||!a) return a;
- int flow=,f;
- for(int& i=cur[u];i<g[u].size();i++) {
- Edge& e=es[g[u][i]];
- int v=e.v;
- if(d[v]==d[u]+&&(f=dfs(v,min(a,e.cap-e.flow)))>) {
- e.flow+=f;
- es[g[u][i]^].flow-=f;
- flow+=f; a-=f;
- if(!a) break;
- }
- }
- return flow;
- }
- int MaxFlow(int s,int t) {
- this->s=s,this->t=t;
- int flow=;
- while(bfs()) {
- memset(cur,,sizeof(cur));
- flow+=dfs(s,inf);
- }
- return flow;
- }
- } dc;
- int T,n,m,ans[N][N],b[N],t[N],vis[N],tot;
- void dfs(int u)
- {
- vis[u]=;
- FOR(i,,(int)dc.g[u].size()-) {
- Edge& e=dc.es[dc.g[u][i]];
- if(!vis[e.v]&&e.cap>e.flow) dfs(e.v);
- }
- }
- void solve(int l,int r)
- {
- if(l==r) return ;
- dc.clear();
- int S=b[l],T=b[r],cut;
- cut=dc.MaxFlow(S,T);
- memset(vis,,sizeof(vis));
- dfs(S);
- FOR(i,,n) if(vis[i])
- FOR(j,,n) if(!vis[j])
- ans[i][j]=ans[j][i]=min(ans[i][j],cut);
- int L=l,R=r;
- FOR(i,l,r)
- if(vis[b[i]]) t[L++]=b[i];
- else t[R--]=b[i];
- FOR(i,l,r) b[i]=t[i];
- solve(l,L-),solve(L,r);
- }
- int main()
- {
- //freopen("in.in","r",stdin);
- //freopen("out.out","w",stdout);
- T=read();
- while(T--) {
- n=read(),m=read();
- dc.init(n+);
- FOR(i,,m) {
- int u=read(),v=read(),w=read();
- dc.AddEdge(u,v,w),dc.AddEdge(v,u,w);
- }
- FOR(i,,n) {
- b[i]=i;
- FOR(j,,n) ans[i][j]=inf;
- }
- solve(,n);
- int q=read();
- while(q--) {
- int x=read(),res=;
- FOR(i,,n) FOR(j,i+,n)
- if(ans[i][j]<=x) res++;
- printf("%d\n",res);
- }
- puts("");
- }
- return ;
- }
bzoj 2229 [Zjoi2011]最小割(分治+最小割)的更多相关文章
- BZOJ 2229 / Luogu P3329 [ZJOI2011]最小割 (分治最小割板题)
题面 求所有点对的最小割中<=c的数量 分析 分治最小割板题 首先,注意这样一个事实:如果(X,Y)是某个s1-t1最小割,(Z,W)是某个s2-t2最小割,那么X∩Z.X∩W.Y∩Z.Y∩W这 ...
- bzoj2229: [Zjoi2011]最小割(分治最小割+最小割树思想)
2229: [Zjoi2011]最小割 题目:传送门 题解: 一道非常好的题目啊!!! 蒟蒻的想法:暴力枚举点对跑最小割记录...绝对爆炸啊.... 开始怀疑是不是题目骗人...难道根本不用网络流?? ...
- BZOJ 4435 [Cerc2015]Juice Junctions 分治最小割+hash
分治最小割的题目,要求n2. 之前用的n3的方法自然不能用了. 于是用hash,设hash[i][j]表示在最小割为i的时候,j是否与S联通. 看懂这个需要理解一下最小割树的构造. 这种题建议用EK写 ...
- 最小割分治(最小割树):BZOJ2229 && BZOJ4519
定理:n个点的无向图的最小割最多n-1个. 可能从某种形式上形成了一棵树,不是很清楚. 最小割分治:先任选两个点求一边最小割,然后将两边分别递归,就能找到所有的最小割. 这两个题是一样的,直接搬din ...
- 【bzoj4519】[Cqoi2016]不同的最小割 分治+最小割
题目描述 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割.对于带权图来说,将所有顶点处在不同 ...
- bzoj 2229: [Zjoi2011]最小割
Description 小白在图论课上学到了一个新的概念--最小割,下课后小白在笔记本上写下了如下这段话: "对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同 ...
- BZOJ.2229.[ZJOI2011]最小割(最小割树)
题目链接 题意:给定一张无向图,求任意两点之间的最小割. 在所有点中任选两个点作为源点\(S\).汇点\(T\),求它们之间的最小割\(ans\),并把原图分成两个点集\(S',T'\),用\(ans ...
- bzoj 2229: [Zjoi2011]最小割【Gomory–Hu tree最小割树】
这个算法详见http://www.cnblogs.com/lokiii/p/8191573.html 求出两两之间最小割之后暴力统计即可 #include<iostream> #inclu ...
- [ZJOI2011]最小割 & [CQOI2016]不同的最小割 分治求最小割
题面: [ZJOI2011]最小割 [CQOI2016]不同的最小割 题解: 其实这两道是同一道题.... 最小割是用的dinic,不同的最小割是用的isap 其实都是分治求最小割 简单讲讲思路吧 就 ...
随机推荐
- 卓京---java基础2
2.数据类型 基本类型: 整型: byte字节型 8位(bit) -2^7~2^7-1(-128~127) 0000 0000 short短整型 16位 -2^15~2^15-1(-32768 ...
- Qt 添加外部库文件(四种方法)
Qt添加外部库文件, 一种就是直接加库文件的绝对路劲,这种方法简单,但是遇到多个库文件的时候,会很麻烦,而且,如果工程移动位置以后还需要重新配置 另一种就是相对路径了,不过Qt 编译的文件会在一个单独 ...
- sudo和su
su命令就是切换用户的工具 sudo 授权许可使用的su,也是受限制的su 1. sudo 的适用条件 由于su 对切换到超级权限用户root后,权限的无限制性,所以su并不能担任多个管理员所管理的系 ...
- 受限波兹曼机导论Introduction to Restricted Boltzmann Machines
Suppose you ask a bunch of users to rate a set of movies on a 0-100 scale. In classical factor analy ...
- ActiveMQ集群(2)
ActiveMQ具有强大和灵活的集群功能,但在使用的过程中会发现很多的缺点,ActiveMQ的集群方式主要有两种:Master-Slave和Broker Cluster. 1.Master-Slave ...
- python3.4安装suds
使用suds访问webservice十分方便 python3.x安装suds会报错“No module named client” 在stackoverflow上找到了替代方法,安装suds-jurk ...
- apk反编译(2)smali语言及文件
Smali语言是Davlik的虚拟机使用的一种语言,用toolapk反编译apk后,可以见到大量的.smali文件. 可以按照smali语法对其修改,然后重新生成一个未签名的apk. 下面是一个示例: ...
- hadoop2的automatic HA+Federation+Yarn配置的教程
前言 hadoop是分布式系统,运行在linux之上,配置起来相对复杂.对于hadoop1,很多同学就因为不能搭建正确的运行环境,导致学习兴趣锐减.不过,我有免费的学习视频下载,请点击这里. hado ...
- AWS 之 S3篇<.NET(c#)批量上传文件>
第一次知道AWS然后网上就研究了一番,如果也是第一次知道这个的话,或者对这个只知道是干什么,并没有写个相关的程序的话,可以看看这个网址http://docs.aws.amazon.com/zh_cn/ ...
- UVa 580 (递推) Critical Mass
题意: 有两种盒子分别装有铀(U)和铅(L),现在把n个盒子排成一列(两种盒子均足够多),而且要求至少有3个铀放在一起,问有多少种排放方法. 分析: n个盒子排成一列,共有2n中方案,设其中符合要求的 ...