381. 有线电视网络

题目链接

381. 有线电视网络

给定一张 n 个点 m 条边的无向图,求最少去掉多少个点,可以使图不连通。

如果不管去掉多少个点,都无法使原图不连通,则直接返回 n

输入格式

输入包含多组测试数据。

每组数据占一行,首先包含两个整数 nm,接下来包含 m 对形如 (x,y) 的数对,形容点 x 与点 y 之间有一条边。

数对 (x,y) 中间不会包含空格,其余地方用一个空格隔开。

输出格式

每组数据输出一个结果,每个结果占一行。

数据范围

0n50

输入样例:

0 0 1 0 3 3 (0,1) (0,2) (1,2) 2 0 5 7 (0,1) (0,2) (1,3) (1,2) (1,4) (2,3) (3,4)

输出样例:

0 1 3 0 2

解题思路

最小割

建图:因为如果不连通的话最后必定有两点不连通,不妨将这两个点作为源点和汇点,即枚举源点 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_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(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; } const int 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]; void add(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++; } bool bfs() { 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)return true; q[++tt]=y; } } } return false; } int dfs(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; } int dinic() { int res=0,flow; while(bfs())while(flow=dfs(S,inf))res+=flow; return res; } int main() { 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); } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16940544.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(71)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示

喜欢请打赏

扫描二维码打赏

支付宝打赏