整理的算法模板合集: ACM模板
目录
最小割,我们建立一个超级源点和超级汇点,做一下最小割,即可得到通过割边使得整张图变成两个完全不相连的集合的最小花费。
同样的,我们也可以指定两个点为源点和汇点,求得通过割边,使得两个点不再连通的最小花费
最大流最小割定理
最小割 = 最大流
一、集合划分模型
有 n 个物品和两个集合 S,T。将一个物品放入 S 集合会花费 ai,放入 T 集合会花费 bi。还有若干个形如 u,v,w
限制条件,表示如果 u 和 v 同时不在一个集合会花费 w。每个物品必须且只能属于一个集合,求最小的代价。
我们对于每个集合设置源点 S 和汇点 T,第 i 个点由 S 连一条容量为 bi的边、向 T 连一条容量为 ai的边。对于限制条件 u,v,w,我们在 u,v 之间连容量为 w 的双向边。注意到当 S 和 T 不相连时,S 能到达 i 代表物品 i 放入 S,i 能到达 T 代表物品 i 放入 T。当割开 S→i 的边,意味着 i 放入 T;当割开 i→T 的边,意味着 i 放入 S;当割开 u,v 之间的边,意味着 u,v 不放入同一个集合。因此最小割就是最小花费。
//SHOI 2007 善意的投票
/*n个人有两种不同的意见并且有许多朋友,需要让朋友间尽可能的统一意见(少发生冲突),如果一个人违反自己的本意也算冲突,求最少的冲突*/
typedef long long ll;
typedef pair<int,int> PII;
const ll INF = 1e18;
const int N = 5e2+7;
const int M = 2e5+7;
int head[N],nex[M],ver[M],tot;
ll edge[M];
int n,m,s,t;
ll maxflow;
ll deep[N];//层级数,其实应该是level
int now[M];//当前弧优化
queue<int>q;
inline void read(int &x){
int f=0;x=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=f?-x:x;
}
inline void add(int x,int y,int z){
//建正边和反向边
ver[tot] = y;
edge[tot] = z;
nex[tot] = head[x];
head[x] = tot ++ ;
}
inline bool bfs(){
//在残量网络中构造分层图
for(int i = 0; i <= n + 1; ++ i)deep[i] = INF;
while(!q.empty())q.pop();
q.push(s);deep[s] = 0;now[s] = head[s];//一些初始化
while(!q.empty()){
int x = q.front();q.pop();
for(int i = head