建图:因为如果不连通的话最后必定有两点不连通,不妨将这两个点作为源点和汇点,即枚举源点 s 和汇点 t,如果是要删除边使图不连通,则很显然删除割边即可,即最小割即为答案,但这里要求删除点,不妨考虑拆点,将所有点拆分为入点和出点,在流网络中入点向出点连一条容量为 1 的边,其他边容量足够大,由最小割要求的是最小的割,或者最大流最小割定理,由于跑最大流是一定要经过点,而点的容量是有限的,即最大流一定是有限的,即最小割有限,最后的割边就相当于是点。另外还有一个优化:不用枚举源点或汇点,即将其中一个固定,为什么?由于固定的点一定在 S 或者 T 中,假设在 S 中,则由于是无向图,即对应流网络中除去入点和出点之间的边其余正边和反边的容量都是足够大,将 s 和固定点交换得到的结果还是一样的(不妨想象成所有的流量逆行)
时间复杂度:O(n5)
代码
// Problem: 有线电视网络// Contest: AcWing// URL: https://www.acwing.com/problem/content/description/383/// Memory Limit: 64 MB// Time Limit: 1000 ms// // Powered by CP Editor (https://cpeditor.org)// %%%Skyqwq#include<bits/stdc++.h>//#define int long long#define help {cin.tie(NULL); cout.tie(NULL);}#define pb push_back#define fi first#define se second#define mkp make_pairusingnamespace std;
typedeflonglong LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> boolchkMax(T &x, T y){ return (y > x) ? x = y, 1 : 0; }
template <typename T> boolchkMin(T &x, T y){ return (y < x) ? x = y, 1 : 0; }
template <typename T> voidinlineread(T &x){
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
constint N=105,M=(55+2500)*2,inf=1e9;
int n,m,S,T;
int h[N],f[M],ne[M],e[M],idx;
int d[N],hh,tt,q[N],cur[N];
voidadd(int a,int b,int c){
e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;
e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
boolbfs(){
memset(d,-1,sizeof d);
d[S]=hh=tt=0;
q[0]=S;
cur[S]=h[S];
while(hh<=tt)
{
int x=q[hh++];
for(int i=h[x];~i;i=ne[i])
{
int y=e[i];
if(d[y]==-1&&f[i])
{
d[y]=d[x]+1;
cur[y]=h[y];
if(y==T)returntrue;
q[++tt]=y;
}
}
}
returnfalse;
}
intdfs(int x,int limit){
if(x==T)return limit;
int flow=0;
for(int i=cur[x];~i&&flow<limit;i=ne[i])
{
cur[x]=i;
int y=e[i];
if(d[y]==d[x]+1&&f[i])
{
int t=dfs(y,min(f[i],limit-flow));
if(!t)d[y]=-1;
f[i]-=t,f[i^1]+=t,flow+=t;
}
}
return flow;
}
intdinic(){
int res=0,flow;
while(bfs())while(flow=dfs(S,inf))res+=flow;
return res;
}
intmain(){
while(~scanf("%d%d",&n,&m))
{
memset(h,-1,sizeof h);
idx=0;
for(int i=1;i<=n;i++)add(i,i+n,1);
for(int i=1;i<=m;i++)
{
int x,y;
scanf(" (%d,%d)",&x,&y);
x++,y++;
add(x+n,y,inf),add(y+n,x,inf);
}
int res=n;
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
{
S=i+n,T=j;
for(int i=0;i<idx;i+=2)f[i]+=f[i^1],f[i^1]=0;
res=min(res,dinic());
}
printf("%d\n",res);
}
return0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!