最小割小记

参考博客:最小割浅谈

关于最小割

  1. 常用描述
    表述一:删去若干条边使得源点到汇点不连通,求删边的权值和的最小可能值。
    表述二:将点集分为(S,T)(S,T)(S,T),记所有从SSS中出发到TTT中的边的权值和为c(S,T)c(S,T)c(S,T),求c(S,T)c(S,T)c(S,T)的最小值。

  2. 求最小割
    a. 以权值为容量,该网络最大流的值即为最小割的值
    b. 在残量网络中,从源点出发进行一次增广BFS,即得到一个分割。该分割是一个最小割。

题型1:对求最小割原理的理解

[AHOI2009]最小割

在这里插入图片描述
在这里插入图片描述
摘自此Blog

[SDOI2014]LIS

在这里插入图片描述
在这里插入图片描述
摘自此Blog

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define re register
#define maxn 1505
#define LL long long
#define inf 999999999
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
inline int read()
{char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct node{int a,b,c,rk;}g[maxn];
inline int cmp(node A,node B) {return A.c<B.c;}
struct E{int v,nxt,w,f;}e[maxn*maxn];
int n,num=1,S,T,Test;
int ans[maxn],cnt,id[maxn],vis[maxn];
int d[maxn],dp[maxn],head[maxn],cur[maxn],in[maxn],out[maxn];
inline void add(int x,int y,int z) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=z;}
inline void C(int x,int y,int z) {add(x,y,z),add(y,x,0);}
inline int check(int s,int t)
{std::queue<int> q;memset(vis,0,sizeof(vis));q.push(s);vis[s]=1;while(!q.empty()){int k=q.front();q.pop();if(k==t) return 1;for(re int i=head[k];i;i=e[i].nxt)if(!vis[e[i].v]&&e[i].w>e[i].f) q.push(e[i].v),vis[e[i].v]=1;}return 0;
}
inline int BFS(int s,int t)
{std::queue<int> q;memcpy(cur,head,sizeof(head));memset(d,0,sizeof(d));d[s]=1,q.push(s);while(!q.empty()){int k=q.front();q.pop();for(re int i=head[k];i;i=e[i].nxt)if(!d[e[i].v]&&e[i].w>e[i].f) {d[e[i].v]=d[k]+1;if(e[i].v==t) return 1;q.push(e[i].v);}}return d[t];
}
int dfs(int x,int now,int t)
{if(x==t||!now) return now;int flow=0,ff;for(re int& i=cur[x];i;i=e[i].nxt)if(d[e[i].v]==d[x]+1){ff=dfs(e[i].v,min(now,e[i].w-e[i].f),t);if(ff<=0) continue;now-=ff,flow+=ff;e[i].f+=ff,e[i^1].f-=ff;if(!now) break;}return flow;
}
int main()
{Test=read();while(Test--){n=read();cnt=0;num=1;memset(head,0,sizeof(head));for(re int i=1;i<=n;i++) g[i].a=read(),dp[i]=1;for(re int i=1;i<=n;i++) g[i].b=read(),g[i].rk=i;for(re int i=1;i<=n;i++)for(re int j=1;j<i;j++) if(g[j].a<g[i].a) dp[i]=max(dp[j]+1,dp[i]);int tot=0;for(re int i=1;i<=n;i++) tot=max(tot,dp[i]);//dp求LIS T=0;for(re int i=1;i<=n;i++) in[i]=++T;for(re int i=1;i<=n;i++) out[i]=++T;++T;for(re int i=1;i<=n;i++) C(in[i],out[i],g[i].b),id[i]=num;for(re int i=1;i<=n;i++) if(dp[i]==1) C(S,in[i],inf);for(re int i=1;i<=n;i++) if(dp[i]==tot) C(out[i],T,inf);for(re int i=1;i<=n;i++)for(re int j=1;j<i;j++) if(g[j].a<g[i].a&&dp[j]+1==dp[i]) C(out[j],in[i],inf);tot=0;while(BFS(S,T)) tot+=dfs(S,inf,T);//建图+跑最小割 for(re int i=1;i<=n;i++) g[i].c=read();printf("%d ",tot);std::sort(g+1,g+n+1,cmp);for(re int i=1;i<=n;i++){int k=g[i].rk;if(check(in[k],out[k])) continue;ans[++cnt]=k;while(BFS(T,out[k])) dfs(T,inf,out[k]);while(BFS(in[k],S)) dfs(in[k],inf,S);e[id[k]].w=e[id[k]^1].w=0;e[id[k]].f=e[id[k]^1].f=0;//退流,排除和当前所选边等价的边的影响 }printf("%d\n",cnt);std::sort(ans+1,ans+cnt+1);for(re int i=1;i<=cnt;i++) printf("%d ",ans[i]);putchar(10);}return 0;
}

题型2:最下生成树相关

例题这里有

题型3:对点的分割 转 对边的分割

[HNOI2013] 切糕
在这里插入图片描述

题型4:最小点割集

最小点割集是指:
给出一张有向图(无向图)和两个点S、T,每个点都有一个正数点权,求一个不包含点S、T的权值和最小的点集使得删掉点集中的所有点后,S无法到达T。

求法:
对于这个问题,我们将每一个点拆成两个点,一个为入点,一个为出点,这两个点之间有一条边权为原图中点权的有向边,从入点指向出点。对于原图中的边x→yx\to yxy,我们将其更改为x的出点→y\to yy的入点。在转化完的图上跑最小割就是原图的最小点割集。

题型5:最小割树——求任意两点的最小割

最小割树
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int n,m,node[505],dep[505],fa[505][10],mn[505][10];
int cnt,top[505],to[1005],len[1005],nex[1005];
int read()
{int re=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();return re;
}
void add_edge(int x,int y,int z)
{to[++cnt]=y,len[cnt]=z,nex[cnt]=top[x],top[x]=cnt;to[++cnt]=x,len[cnt]=z,nex[cnt]=top[y],top[y]=cnt;
}
namespace GHT
{int s,t;int tot,cur[505],dep[505],col[505],col_bucket[505];int cnt=1,top[505],to[3005],cap[3005],flow[3005],nex[3005];void add_edge(int x,int y,int z){to[++cnt]=y,cap[cnt]=z,flow[cnt]=0,nex[cnt]=top[x],top[x]=cnt;to[++cnt]=x,cap[cnt]=z,flow[cnt]=0,nex[cnt]=top[y],top[y]=cnt;//注意这里 }bool BFS(){memset(cur,0,sizeof cur);memset(dep,0,sizeof dep);dep[s]=1,cur[s]=top[s];queue<int>Q;Q.push(s);while(!Q.empty()){int now=Q.front();Q.pop();for(int i=top[now];i;i=nex[i])if(!dep[to[i]]&&cap[i]>flow[i]){dep[to[i]]=dep[now]+1;cur[to[i]]=top[to[i]];Q.push(to[i]);}}return dep[t]!=0;}int DFS(int now,int rest){if(now==t) return rest;int re=0;for(int &i=cur[now];i;i=nex[i])if(dep[to[i]]==dep[now]+1&&cap[i]>flow[i]){int lzq=DFS(to[i],min(rest,cap[i]-flow[i]));if(lzq){rest-=lzq,re+=lzq;flow[i]+=lzq,flow[i^1]-=lzq;//注意这里 if(!rest) break;}}return re;}int Dinic(int x,int y){int re=0;s=x,t=y;for(int i=1;i<=cnt;i++) flow[i]=0;while(BFS()) re+=DFS(s,0x3f3f3f3f);return re;}void get_color(int now,int color){col[now]=color;for(int i=top[now];i;i=nex[i])if(cap[i]>flow[i]&&col[to[i]]!=color)//注意这里 get_color(to[i],color);}void build(int l,int r){if(l==r) return ;int x=node[l],y=node[l+1];int cut=Dinic(x,y);get_color(x,++tot);int L=l,R=r;for(int i=l;i<=r;i++)if(col[node[i]]==tot) col_bucket[L++]=node[i];else col_bucket[R--]=node[i];for(int i=l;i<=r;i++) node[i]=col_bucket[i];::add_edge(x,y,cut);build(l,L-1);build(R+1,r);}
}
void dfs(int now)
{for(int i=1;i<=9;i++){fa[now][i]=fa[fa[now][i-1]][i-1];mn[now][i]=min(mn[now][i-1],mn[fa[now][i-1]][i-1]);}for(int i=top[now];i;i=nex[i]){if(to[i]==fa[now][0]) continue;dep[to[i]]=dep[now]+1,fa[to[i]][0]=now,mn[to[i]][0]=len[i];dfs(to[i]);}
}
int getcut(int x,int y)
{int re=INT_MAX;if(dep[x]<dep[y]) swap(x,y);for(int i=9;i>=0;i--) if(dep[fa[x][i]]>=dep[y]) re=min(re,mn[x][i]),x=fa[x][i];if(x==y) return re;for(int i=9;i>=0;i--) if(fa[x][i]!=fa[y][i]) re=min(re,min(mn[x][i],mn[y][i])),x=fa[x][i],y=fa[y][i];return min(re,min(mn[x][0],mn[y][0]));
}
int main()
{n=read(),m=read();while(m--){int x=read(),y=read(),z=read();GHT::add_edge(x,y,z);}for(int i=1;i<=n;i++) node[i]=i;GHT::build(1,n);dep[1]=1;dfs(1);m=read();while(m--){int x=read(),y=read();printf("%d\n",getcut(x,y));}return 0;
}

题型6:最大权闭合子图

闭合子图指的是,对于有向图,我们选择一些点,在这个点集之中,没有一个点的出边指向非此点集中的点,但是可以有其他点的出边指向这个点集之中。所说的最大权闭合子图,就是在这个图的所有闭合子图中点权和最大的。

求法:
建立源点,向每一个点权为正的点连边,边权为该点的权值。建立汇点,向每一个点权为负连边,边权为该点的权值的绝对值。原图中的边进行保留,边权为infinfinf。最大权闭合子图就是所有的点权为正的点权和减去最小割。

在这里插入图片描述
在这里插入图片描述

题型7:划分点集

(u→v,w)(u\to v,w)(uv,w)为一条从uuuvvv,权值为www的边。

基础模型

nnn个点划分到两个集合A,BA,BA,B。给出若干形如 “若…,则有…的代价/贡献” 的条件。问最大贡献/最小代价是多少。

如果题目问的是最小代价,直接按下面方法连边求最小割。
如果题目问的是最大贡献,答案为∑所有可能贡献−最小代价(最小割)\sum 所有可能贡献-最小代价(最小割)()

定义和SSS相连的点划到AAA集合,和TTT相连的点划到BBB集合,那么我们可以按下面的方法处理题目给出的条件:

  1. 条件-表述1:若把iii划到AAA,则要付出bib_ibi的代价;若把iii划到BBB,则要付出aia_iai的代价
    条件-表述2:若把iii划到BBB,则有bib_ibi的贡献;若把iii划到AAA,则有aia_iai的贡献
    方案:(i→T,bi)(i\to T,b_i)(iT,bi),(S→i,ai)(S\to i,a_i)(Si,ai)
  2. 条件-表述1:若点集XXX中有元素划到BBB,则要付出ccc的代价
    条件-表述2:若点集XXX中元素全部划到AAA,则有ccc的贡献
    方案:(S→new,c),∀i∈X(new→i,inf)(S\to new,c),\forall i\in X(new\to i,inf)(Snew,c),iX(newi,inf)
  3. 条件-表述1:若点集XXX中有元素划到AAA,则要付出ddd的代价
    条件-表述2:若点集XXX中元素全部划到BBB,则有ddd的贡献
    方案:∀i∈X(i→new,inf),(new→T,d)\forall i\in X(i\to new,inf),(new\to T,d)iX(inew,inf),(newT,d)
  4. 条件:若点集XXX中有元素划到BBB,点集YYY中有元素划到AAA,则要付出eee的代价
    常见形式:若点iii划到BBB,点jjj划到AAA,则要付出eee的代价
    方案:∀i∈X(new1→i,inf)\forall i\in X(new1\to i,inf)iX(new1i,inf),∀j∈Y(j→new2,inf)\forall j\in Y(j\to new2,inf)jY(jnew2,inf),(new2→new1,e)(new2\to new1,e)(new2new1,e)
  5. 条件:若点集XXX中有元素划到AAA,点集YYY中有元素划到BBB,则要付出fff的代价
    常见形式:若点iii划到AAA,点jjj划到BBB,则要付出fff的代价
    方案:∀i∈X(i→new1,inf)\forall i\in X(i\to new1,inf)iX(inew1,inf),∀j∈Y(new2→j,inf)\forall j\in Y(new2\to j,inf)jY(new2j,inf),(new1→new2,f)(new1\to new2,f)(new1new2,f)

[Shoi2007]Vote 善意的投票

BZOJ3438: 小M的作物

[BZOJ3218]a + b Problem

处理变形问题的trick:黑白染色,翻转源汇

对于“x,yx,yx,y必须划到不同集合” “x,yx,yx,y划到不同集合有ccc的贡献” “x,yx,yx,y划到相同集合有ddd的代价”这样的条件,我们可以连边(x,y)(x,y)(x,y),黑白染色后x,yx,yx,y一定一个是黑点,一个是白点。

如果将其中一种颜色的点进行翻转源汇,即原本应该连向SSS的边连向TTT,原本应该连向TTT的边连向SSS,那么“x,yx,yx,y在不同集合”就变成了“x,yx,yx,y在相同集合”,“x,yx,yx,y在相同集合”就变成了“x,yx,yx,y在不同集合”

BZOJ1324Exca王者之剑&BZOJ1475方格取数——二分图最大独立集

[BZOJ2132]圈地计划——翻转源汇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319915.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CF204E-Little Elephant and Strings【广义SAM,线段树合并】

正题 题目链接:https://www.luogu.com.cn/problem/CF204E 题目大意 nnn个字符串的一个字符串集合&#xff0c;对于每个字符串求有多少个子串是这个字符串集合中至少kkk个字符串的子串。 解题思路 因为对于每个字符串我们需要维护的信息不同&#xff0c;不能累加&#xff0c;所…

【莫队】区间不同数(金牌导航 莫队-1)

区间不同数 金牌导航 莫队-1 题目大意 给出n个数&#xff0c;然后询问m次&#xff0c;每次询问一个区间内不同的数的个数 样例输入 6 1 2 3 4 3 5 3 1 2 3 5 2 6样例输出 2 2 4数据范围 1⩽n⩽5104,1⩽m⩽2105,0⩽ai⩽1061\leqslant n\leqslant 5\times 10^4,1\leqslant …

斐波那契数列求法

文章目录求斐波那切数列的几个方法&#xff1a;经典做法&#xff1a;递推&#xff1a;动态规划矩阵快速幂原理&#xff1a;代码&#xff1a;例题&#xff1a;模拟过程求斐波那切数列的几个方法&#xff1a; 经典做法&#xff1a; 众所周知&#xff1a;斐波那契数列的定义是f(…

ASP.Net Core2.1中的HttpClientFactory系列一

引言&#xff1a;ASP.NET Core2.1 中出现了一个新的 HttpClientFactory 功能, 它有助于解决开发人员在使用 HttpClient 实例从其应用程序中访问外部 web 资源时可能遇到的一些常见问题。关于HttpClientFactory 到底解决了那些HttpClient的严重问题&#xff0c;下面是我罗列出来…

欧拉回路哈密顿回路

欧拉回路 总结 百度百科 混合图的欧拉回路 Fleury算法 Hierholzer算法 //寻找无向图的欧拉路径 #include<iostream> #include<vector> #include<stack> using namespace std; vector<int> g[1001]; int n,m,x,y,d[1001],s-1,t-1; bool vis[1001][100…

【CDQ分治】三维偏序(luogu 3801/金牌导航 CDQ分治-1)

三维偏序 luogu 3801 金牌导航 CDQ分治-1 题目大意 有n个元素&#xff0c;第i个元素有ai,bi,cia_i,b_i,c_iai​,bi​,ci​三个属性&#xff0c;设 f(i)表示满足aj⩽aia_j\leqslant a_iaj​⩽ai​且bj⩽bib_j \leqslant b_ibj​⩽bi​且cj⩽cic_j \leqslant c_icj​⩽ci​且…

P4929-[模板]舞蹈链(DLX)

正题 题目链接:https://www.luogu.com.cn/problem/P4929 题目大意 n∗mn*mn∗m的矩形有0/10/10/1&#xff0c;要求选出若干行使得每一列有且仅有一个111。 解题思路 精确覆盖问题指的是一个集合SSS和它的若干个子集集合TTT&#xff0c;要求选出TTT的一个子集使得里面的集合元…

最大子矩阵(普通和01)

文章目录普通矩阵&#xff08;单个矩阵值为任何数&#xff09;最大子段和扩展到二维情况01矩阵&#xff08;单个矩阵值为0或1&#xff09;代码&#xff1a;普通矩阵&#xff08;单个矩阵值为任何数&#xff09; 例题&#xff1a;POJ 1074 求出其中最大的子矩阵 答案是&#x…

自动化流程开源框架BotSharp

BotSharp是一款为方便构建智能对话机器人平台而开发的开源框架&#xff0c;最大的特点是所有模型算法都是基于.NET Core开发实现&#xff0c;甚至最基本的Penn Treebank分词标准&#xff0c;都重新用C#实现了。在机器学习python占绝对优势的时代算是不可多得的项目。该项目涉及…

二分图匹配

定义&#xff1a; 二分图&#xff1a;一个图被分成了两部分&#xff0c;相同的部分没有边 匹配&#xff1a;二分图G的子图M中&#xff0c;M的边集{E}中的任意两条边都不指向同一个顶点 极大匹配&#xff1a;在当前已完成的匹配下,无法再通过增加未完成匹配的边的方式来增加匹…

【整体二分】区间第k小(金牌导航 整体二分-1)

区间第k小 金牌导航 整体二分-1 题目大意 给出一个序列&#xff0c;有若干查询&#xff0c;每次查询给出l,r,k&#xff0c;让你求l~r这个区间的第k大 输入样例 7 3 1 5 2 6 3 7 4 2 5 3 4 4 1 1 7 3输出样例 5 6 3数据范围 1⩽n⩽105,1⩽m⩽50000,1⩽∣ai∣⩽1091\leqsla…

积极参与开源项目,促进.NET Core生态社区发展

今天早上在微信群里聊天聊到百度的SDK 已经支持.NET Core, 百度已经在3月份就支持了&#xff0c;想起当时还是我在他们的github上提的issue&#xff1a; https://github.com/Baidu-AIP/dotnet-sdk/issues/3。.NET Core生态社区的发展已经四年多时间&#xff0c;日趋完善&#x…

P6091-[模板]原根

正题 题目链接:https://www.luogu.com.cn/problem/P6091 题目大意 给出一个数ppp&#xff0c;求出它的所有在[0,p][0,p][0,p]的原根。 解题思路 原根的定义&#xff0c;δp(a)\delta_p(a)δp​(a)表示一个最小的nnn使得an≡1(modp)a^n\equiv1(mod\ p)an≡1(mod p)&#xff0…

并查集小记

有什么用&#xff1a; 查询元素a和元素b是否属于同一组 合并元素a和元素b所在组 代码实现&#xff1a; #include<iostream> using namespace std; int n,m,p; int fa[5001]; int find(int x){if(fa[x]x) return x;else{return fa[x]find(fa[x]);} } int main(){cin&g…

Poj 1011 UVA - 307 Sticks

牛客网 poj 1011 题目&#xff1a; George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long th…

HAPPY2020暑假训练前复习

A.计蒜客 - T1381 输出hello world 万恶之源 B.51Nod - 2060 全排列输出 不要用STL的next_permutation,会超时 #include <bits/stdc.h> using namespace std; const int maxn14; int dt[maxn]; int vis[maxn];int n; void dfs(int depth) {if(depthn){for(int i0;; i…

【LCT】洞穴勘测(luogu 2147/金牌导航 LCT-1)

洞穴勘测 luogu 2147 金牌导航 LCT-1 题目大意 给你若干操作&#xff0c;有三种操作&#xff1a; 1.连接两个点 2.吧两个点之间的连边断掉&#xff08;保证有这条边&#xff09; 3.查询两个点之间是否连通 样例 #1 输入样例 #1 200 5 Query 123 127 Connect 123 127 Que…

Service Fabric 与Ocelot 的集成

概要云应用程序通常都需要使用前端网关&#xff0c;为用户、设备或其他应用程序提供同一个入口点。 在 Service Fabric 中&#xff0c;网关可以是任意无状态服务&#xff08;如 ASP.NET Core 应用程序&#xff09; 。本文介绍了如何将Ocelot用作 Service Fabric 应用程序的网关…

图论复习——最短路

知识点 最短路径算法 最短路径树 每个点uuu的父亲为使uuu得到最短距离的前驱节点&#xff0c;若有多个&#xff0c;则取任意一个。 题目 CF449B Jzzhu and Cities Blog CF464E The Classic Problem Blog [XSY3888] 传送门 对每个点uuu&#xff0c;记d(u)d(u)d(u)表示uuu…

Loj#143-[模板]质数判定【Miller-Rabin】

正题 题目链接:https://loj.ac/p/143 题目大意 给出一个数ppp&#xff0c;让你判定是否为质数。 解题思路 Miller−RabinMiller-RabinMiller−Rabin是一种基于费马小定理和二次探测定理的具有较高正确性的高效质数判定算法。 首先讲一下两个定理 费马小定理&#xff1a;gcd(…