Nubulsa Expo (全局最小割)
一、前言
全局最小割板题。
二、题目
求给定源点的无向图最小割。
三、讲解
(一)、科技:全局最小割
首先我们有个连我都能感性理解的算法:任选两个点,求出最小割并更新答案,合并这两个点,最后求出的答案即为全局最小割。这其实就是并不出名大名鼎鼎的 Stoer-Wagner算法。
由于是任选两个点求最小割,所以我们其实有比跑网络流更快的做法:
我们搞一个点集 ,初始里面随便放个点,每次选择 最大的点加入点集。
设第 次加入的点是 ,那么 割开的点集为 。
所以做一次上述做法就可以得到随机两个点的最小割,做 次就可以得到全局最小割。
这个过程可以用类似 Prim 或者说无堆优化的 dijkstra 的方式实现,时间复杂度是 的,如果用堆优化,复杂度是 的。
证明啥的可以去看集训队论文。
(二)、正题
之所以叫正题是因为这篇博客本应是题解。
我们可以注意到这个源点其实没啥用,我们要求的就是全局最小割,证明的话你就考虑全局最小割会把源点 割到一边,在另一边随便选个点其实就是题目所求给定源点的最小割。
知道这个就可以直接上板子了。
我用的是 的做法。
四、代码
//12252024832524
#include <bits/stdc++.h>
#define TT template<typename T>
using namespace std;
typedef long long LL;
const int MAXN = 305;
const int MAXM = 50005;
const LL INF = 1ll << 60;
int n,m;
LL Read()
{
LL x = 0,f = 1;char c = getchar();
while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
return x * f;
}
TT void Put1(T x)
{
if(x > 9) Put1(x/10);
putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
if(x < 0) putchar('-'),x = -x;
Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}
bool vis[MAXN],vis2[MAXN];
LL e[MAXN][MAXN],dis[MAXN];
void Add_Double_Edge(int u,int v,int w){
e[u][v] += w;
e[v][u] += w;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
while(1){
LL ans = INF;
n = Read(); m = Read(); Read();
if(!n && !m) return 0;
for(int i = 1;i <= n;++ i) vis[i] = 0;
for(int i = 1;i <= n;++ i) for(int j = 1;j <= n;++ j) e[i][j] = 0;
for(int i = 1,u,v;i <= m;++ i) u = Read(),v = Read(),Add_Double_Edge(u,v,Read());
for(int cas = 1;cas < n;++ cas){//contract
int now = 0,lst = 0,cnt = 0;
for(int i = 1;i <= n;++ i){//begin
if(!vis[i]) now = i,++cnt;
dis[i] = 0;
}
for(int i = 1;i <= n;++ i) if(!vis[i]) dis[i] = e[now][i],vis2[i] = 0;
vis2[now] = 1;
for(int i = 1;i < cnt;++ i){
lst = now; dis[now] = -1;
for(int j = 1;j <= n;++ j) if(!vis2[j] && dis[j] > dis[now]) now = j;
vis2[now] = 1;
for(int j = 1;j <= n;++ j) if(!vis2[j]) dis[j] += e[now][j];
}
ans = Min(ans,dis[now]); vis[now] = 1;
for(int i = 1;i <= n;++ i) e[lst][i] += e[now][i],e[i][lst] += e[i][now];
}
Put(ans,'\n');
}
return 0;
}
分类:
图论---网络流
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App