链接1
链接2

题意简述

第一个题 : 问图中有多少不同的最小割数值
第二个题 : \(q\) 次询问图中多少对点对之间的最小割小于 \(x\) 。

Sol

两个都是模板题就放一起了。

求完最小割树直接暴力 \(O(n^2)\) 弄出所有点对间最小割 , 然后该干嘛干嘛。


最小割树的构建:

\(Gemory-Hu\; Tree\)算法

对于一个 \(n\) 个节点的图 , 图中所有点对不同的最小割数目最多只有 \(n-1\) 个 , 可以证明存在一棵树 , 使得两点在这棵树上的最小割即为原图中的最小割 。
考虑3个点两两之间的最小割 \(C_{u,v},C_{u,t},C_{v,t}\) , 我们已知 \(C_{u,t},C_{v,t}\) , 假设在\(C_{u,v}\)中 ,不妨假设 \(t\) 被分在了与 \(v\) 在一起的割集 。由于在一个割中一个点一定被分在源点或者汇点的一侧割集 , 那么可以推出 \(C_{u,v}\leq C_{u,t}\) , 如果不是那么显然直接割掉 \(u,t\) 就能达到割掉 \(u,v\) 的目的而使最小割变小。
类似的可以得出 \(C_{u,v}\geq C_{u,t}\) , 那么只能是 \(C_{u,v}=C_{u,t}\) 。
用归纳法可以得到一个 \(n\) 个点的图中最多只有 \(n-1\) 个不同的最小割。

如何构建最小割树?

采用递归的策略 , 对于当前点集 , 任意取两个点做最小割(注意这里是对原图跑最小割) , 然后给这两个点连边 , 权值为最小割大小。
然后就把参与网络中与源点可达的点与源点扔在一起 , 与其他的和汇点扔在一起。两边递归即可。
正确性就是证明只有 \(n-1\) 个不同的最小割中的道理相同 , 考虑某一个点被划分在哪个集合从而保证了正确性。

代码:

cpp1:

#include<bits/stdc++.h>
using namespace std;
#define Set(a,b) memset(a,b,sizeof(a))
#define Copy(a,b) memcpy(a,b,sizeof(a))
template<class T> inline void init(T&x){x=0;char ch=getchar();bool t=0;for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);if(t) x=-x;
}
const int M=3020;
const int N=200;
const int INF=2e9;
struct edge{int to,next,cap,flow;
}a[M<<1];
int head[N],cnt=0;
int que[N],n,m;
inline void add(int x,int y,int z){a[cnt]=(edge){y,head[x],z,z};head[x]=cnt++;}
int d[N],S,T,cur[N];
bool bel[N];queue<int> Q;
inline bool bfs(){while(!Q.empty())Q.pop();Set(d,0);d[S]=1;Q.push(S);while(!Q.empty()){int u=Q.front();Q.pop();for(int v,i=head[u];~i;i=a[i].next){v=a[i].to;if(d[v]||!a[i].cap) continue;d[v]=d[u]+1;if(v==T) return 1;Q.push(v);}}return d[T];
}
int dfs(int u,int flow){if(u==T) return flow;int rest=flow;for(int v,&i=cur[u];~i;i=a[i].next){v=a[i].to;if(!a[i].cap||d[v]!=d[u]+1) continue;int f=dfs(v,min(a[i].cap,rest));if(!f) d[v]=0;rest-=f;a[i].cap-=f,a[i^1].cap+=f;if(!rest) break;}return flow-rest;
}
inline int Dinic(){int flow=0;while(bfs()) Copy(cur,head),flow+=dfs(S,INF);return flow;
}
inline void Return(){for(int i=0;i<cnt;++i) a[i].cap=a[i].flow;for(int i=1;i<=n;++i) bel[i]=0;}
void Dfs(int u){bel[u]=1;for(int v,i=head[u];~i;i=a[i].next){v=a[i].to;if(a[i].cap&&!bel[v]) Dfs(v);}}
namespace GHT{struct edge{int to,next,w;}a[N<<1];int head[N],cnt=0;inline void add(int x,int y,int z){a[++cnt]=(edge){y,head[x],z};head[x]=cnt;}int tmp[N];inline void Clear(){Set(head,0);cnt=0;}void Build(int l,int r){if(l>=r) return;S=que[l],T=que[r];Return();int Flow=Dinic();Dfs(S);int L=l-1,R=r+1;add(S,T,Flow),add(T,S,Flow);for(int i=l;i<=r;++i) {int u=que[i];if(bel[u]) tmp[++L]=u;else tmp[--R]=u;}for(int i=l;i<=r;++i) que[i]=tmp[i];Build(l,L),Build(R,r);return;}int gezi[N*N];inline void DFS(int u,int fa,int Mi){if(Mi!=INF) gezi[++gezi[0]]=Mi;for(int v,i=head[u];i;i=a[i].next){v=a[i].to;if(v==fa) continue;DFS(v,u,min(Mi,a[i].w));}}inline void work(){for(int i=1;i<=n;++i) que[i]=i;Build(1,n);gezi[0]=0;for(int i=1;i<=n;++i) DFS(i,0,INF);sort(gezi+1,gezi+1+gezi[0]);int q;init(q);while(q--){int x;init(x);printf("%d\n",(upper_bound(gezi+1,gezi+1+gezi[0],x)-gezi-1)/2);}puts("");return;}
}
int main()
{int T;init(T);while(T--){Set(head,-1);cnt=0;GHT::Clear();init(n),init(m);int u,v,w;for(int i=1;i<=m;++i) {init(u),init(v),init(w);add(u,v,w),add(v,u,w);}GHT::work();}return 0;
}

cpp2:

#include<bits/stdc++.h>
using namespace std;
#define Set(a,b) memset(a,b,sizeof(a))
#define Copy(a,b) memcpy(a,b,sizeof(a))
template<class T> inline void init(T&x){x=0;char ch=getchar();bool t=0;for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);if(t) x=-x;
}
const int M=8501;
const int N=1000;
const int INF=2e9;
struct edge{int to,next,cap,flow;
}a[M<<1];
int head[N],cnt=0;
int que[N],n,m;
inline void add(int x,int y,int z){a[cnt]=(edge){y,head[x],z,z};head[x]=cnt++;}
int d[N],S,T,cur[N];
bool bel[N];queue<int> Q;
inline bool bfs(){while(!Q.empty())Q.pop();Set(d,0);d[S]=1;Q.push(S);while(!Q.empty()){int u=Q.front();Q.pop();for(int v,i=head[u];~i;i=a[i].next){v=a[i].to;if(d[v]||!a[i].cap) continue;d[v]=d[u]+1;if(v==T) return 1;Q.push(v);}}return d[T];
}
int dfs(int u,int flow){if(u==T) return flow;int rest=flow;for(int v,&i=cur[u];~i;i=a[i].next){v=a[i].to;if(!a[i].cap||d[v]!=d[u]+1) continue;int f=dfs(v,min(a[i].cap,rest));if(!f) d[v]=0;rest-=f;a[i].cap-=f,a[i^1].cap+=f;if(!rest) break;}return flow-rest;
}
inline int Dinic(){int flow=0;while(bfs()) Copy(cur,head),flow+=dfs(S,INF);return flow;
}
inline void Return(){for(int i=0;i<cnt;++i) a[i].cap=a[i].flow;for(int i=1;i<=n;++i) bel[i]=0;}
void Dfs(int u){bel[u]=1;for(int v,i=head[u];~i;i=a[i].next){v=a[i].to;if(a[i].cap&&!bel[v]) Dfs(v);}}
namespace GHT{struct edge{int to,next,w;}a[N<<1];int head[N],cnt=0;inline void add(int x,int y,int z){a[++cnt]=(edge){y,head[x],z};head[x]=cnt;}int tmp[N];void Build(int l,int r){if(l>=r) return;S=que[l],T=que[r];Return();int Flow=Dinic();Dfs(S);int L=l-1,R=r+1;add(S,T,Flow),add(T,S,Flow);for(int i=l;i<=r;++i) {int u=que[i];if(bel[u]) tmp[++L]=u;else tmp[--R]=u;}for(int i=l;i<=r;++i) que[i]=tmp[i];Build(l,L),Build(R,r);return;}map<int,int>vis;int ans=0;inline void DFS(int u,int fa,int Mi){if(Mi!=INF) {if(!vis.count(Mi)) vis[Mi]=1,++ans;}for(int v,i=head[u];i;i=a[i].next){v=a[i].to;if(v==fa) continue;DFS(v,u,min(Mi,a[i].w));}}inline void work(){for(int i=1;i<=n;++i) que[i]=i;Build(1,n);for(int i=1;i<=n;++i) DFS(i,0,INF);cout<<ans<<endl;return;}
}
int main()
{Set(head,-1);init(n),init(m);int u,v,w;for(int i=1;i<=m;++i) {init(u),init(v),init(w);add(u,v,w),add(v,u,w);}GHT::work();return 0;
}

转载于:https://www.cnblogs.com/NeosKnight/p/10443948.html

【LuoguP33294123】[ZJOI2011]最小割[CQOI2016]不同的最小割相关推荐

  1. 【图割】最大流/最小割算法详解(Yuri Boykov and Vladimir Kolmogorov,2004 )

    本博客主要翻译了Yuri Boykov and Vladimir Kolmogorov在2004年发表的改进最大流最小割算法用于计算机视觉的论文:An Experimental Comparison ...

  2. 最大匹配、最小顶点覆盖、最大独立集、最小路径覆盖(转)

    在讲述这两个算法之前,首先有几个概念需要明白: 二分图:  二分图又称二部图,是图论中的一种特殊模型.设G=(V,E)是一个无向图,如果顶点V可以分割为两个互不相交的子集(A,B),并且图中的每条边( ...

  3. 信息学奥赛一本通 1344:【例4-4】最小花费 | 洛谷 P1576 最小花费

    [题目链接] ybt 1344:[例4-4]最小花费 洛谷 P1576 最小花费 [题目考点] 1. 图论 单源最短路径 时间复杂度: Dijkstra算法: O(V2)O(V^2)O(V2) Dij ...

  4. php设置页面最小高度,HTML_CSS布局中最小高度的妙用,最小高度可以设定一个BOX的最 - phpStudy...

    CSS布局中最小高度的妙用 最小高度可以设定一个BOX的最小高度,当其内容较少时时,也能保持BOX的高度为一定,超出就自动向下延伸,但到目前为止,只有Opera 和 Mozilla 支持,IE7开始也 ...

  5. 机器学习十大经典算法:深入浅出聊贝叶斯决策(贝叶斯公式,最小风险贝叶斯,最小错误贝叶斯)

    前言    常听人说,在学习一个东西时,如果能够深入浅出的讲给别人听,才算是真的懂了.最近正好在学模式识别,于是就用它来练笔了.贝叶斯决策(Bayes Decision) 是十大经典机器学习算法之一, ...

  6. 最小表示串 学习【最小表示串 学习(粗)】

    问题 对于一个字符串S,求S的循环的同构字符串S'中字典序最小的一个. 八卦 最小表示法是由IOI2003年冬令营的周源提出来的 周源是 2009年4月21日,第33届ACM国际大学生程序设计竞赛总决 ...

  7. 最小错误率的贝叶斯决策和最小风险贝叶斯决策的关系?

    1.基于最小错误率的贝叶斯决策 共w1~wn种决策 本质上就是最大后验概率P(wi | X)的贝叶斯决策 公式一:P(wi | X) = P(X | wi)*P(wi) / ∑nj=1 P(X | w ...

  8. 接口上线平滑处理_业务系统割接上线关键点和割接方案内容说明

    今天谈下业务系统割接上线方案的内容,对于大项目来说,业务系统在建设完成并UAT测试通过后,最终的割接上线往往是一个系统工程,不能有丝毫的马虎. 系统割接上线概述 临近项目上线,最近周末都在加班处理上线 ...

  9. 弦割法matlab求x 3,用matlab程序实现单点弦割法和双点弦割法解方程

    <用matlab程序实现单点弦割法和双点弦割法解方程>由会员分享,可在线阅读,更多相关<用matlab程序实现单点弦割法和双点弦割法解方程(2页珍藏版)>请在人人文库网上搜索. ...

最新文章

  1. Python描述性统计示例
  2. 如何将SAP云平台Neo环境的Subaccount注册到IAS服务里
  3. 养鹿专辑二:恋鹿篇之枕着老婆的梦编程
  4. 20165205 2017-2018-2 《Java程序设计》实验三 敏捷开发与XP实践
  5. 如何在EJB3中JNDI调用SessionBean(二)
  6. Linux进程间通信IPC学习笔记之同步一(线程、互斥锁和条件变量)
  7. 微信小游戏 UserInfoButton 获取用户信息
  8. 数据结构c语言版秦锋,数据结构(C语言版)黄国瑜.pdf
  9. 微信小程序CanvasContext.drawImage的用法
  10. arccotx图像在matlab,arccotx图像(cotx的定义域和图像)
  11. C++ Qt获取windows任务栏的位置及高度
  12. 小米手机--刷机指南
  13. FIR滤波器(1)- 基础知识
  14. docker 搭建在线office--onlyoffice (一)
  15. Linux下如何让程序以管理员权限运行
  16. 【java毕业设计】基于javaEE+原生Servlet+jsp的人力资源管理系统设计与实现(毕业论文+程序源码)——人力资源管理系统
  17. Postman入门教程【没有废话,直入实战,绝对给力!】
  18. STME32使用RTOS与ADC_DMA冲突
  19. 罗斯蒙特变送器的接线方式
  20. 物联网的未来:无源传输网络

热门文章

  1. HTML5 拖拽的简单实践
  2. Spring4 学习系列之——jdbc事务的基本实现和了解
  3. fake it till you become it
  4. 水瓶座和什么座最配:天秤座,双子座,狮子座
  5. 链接写不到txt文件该怎么办呢
  6. teacher want middle point result rather all drafts
  7. how to find your partner
  8. if the price goes high
  9. 吃完晚饭干什么的好方法
  10. c# nullable类型有什么用