POJ 1966 Cable TV Network (最大流最小割)
$ POJ1966CableTVNetwork $
$ solution: $
第一眼可能让人很难下手,但本就是冲着网络流来的,所以我们直接一点。这道题我们要让这个联通图断开,那么势必会有两个点变得不连通,这道题的数据范围很小,所以我们试着暴力枚举两个点。这样就变成了最小割。不过,嗯?割的东西怎么是点?
为了靠近我们已经学得知识,我们想办法看,能不能割点变成割边。反正网络流最喜欢千变万化、左右建模了。。。于是我们引进书上的一个东西:
- 一个节点可以拆成两个节点,将原节点用中间那条边表示
- 一条边可以拆成两条边,将原边用中间那个点表示
- 中间的边权为1代表这个点是否被割,旁边的边权为inf是为了排除其影响(因为它不可能被割掉)
我们用第一条和第三条性质可以解决这个问题。首先对于每个节点建立两个 $ i $ 和 $ i+n $ 节点。然后这两个节点之间用一条权值为1的有向边(从 $ i $ 到 $ i+n $ ) ,如果这条边在最小割中被割掉(等价于原本的点被割掉)。然后 $ i $ 节点连入边(权值正无穷), $ i+n $ 节点连出边(权值正无穷),连正无穷是为了让割掉的边只能是中间的边。然后我们跑一遍最大流,它对应的最小割里每条代表原来一个点,因为权值为1,所以流量就是答案。
注意:我们的源汇点也要被分为两个点,而网络流中的实际源点是 $ S+n $ ,它连出边。因为源汇点的性质,这两个点不可能被割掉,所以它们中间不连边。
$ code: $
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define db double
#define rg register int
using namespace std;
int n,m,S,T;
int ans,top=1;
int dep[505];
int tou[505];
int qi[505];
int f[55][55];
struct su{
int to,v,next;
}b[5005];
inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
if(sign)return -res; else return res;
}
inline void add(int x,int y,int v){ //注意博主加边自带反向
b[++top]=su{y,v,tou[x]}; tou[x]=top;
b[++top]=su{x,0,tou[y]}; tou[y]=top;
}
inline bool bfs(int x){
for(rg i=1;i<=x;++i)
qi[i]=tou[i],dep[i]=0;
queue<int> q; q.push(S); dep[S]=1;
while(!q.empty()){
rg i=q.front(); q.pop();
for(rg j=tou[i];j;j=b[j].next)
if(b[j].v&&!dep[b[j].to]){
dep[b[j].to]=dep[i]+1;
if(b[j].to==T)return 1;
q.push(b[j].to);
}
} return 0;
}
inline int dfs(int i,int w){
if(i==T||!w)return w;
rg rest=w,f;
for(rg &j=qi[i];j;j=b[j].next){
if(b[j].v&&dep[b[j].to]==dep[i]+1){
f=dfs(b[j].to,min(w,b[j].v));
if(!f){dep[b[j].to]=-2; continue;}
b[j].v-=f; b[j^1].v+=f; w-=f;
} if(!w)break;
}return rest-w;
}
inline void solve(){
rg res=0; top=1;
for(rg i=1;i<=n*2+2;++i) tou[i]=0; //初始化
for(rg i=1;i<=n;++i){
if(i!=S&&i!=T)add(i,i+n,1); //一点拆成两点,中间连边
for(rg j=1;j<=n;++j)
if(f[i][j])add(i+n,j,1e9); //连边注意是否有加n操作
} S=S+n;
while(bfs(n*2+2)) res+=dfs(S,1e9); //DInic
ans=min(res,ans);
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
rg t=qr();
while(t--){
n=qr();m=qr();
for(rg i=1;i<=n;++i){
for(rg j=i;j<=n;++j){
f[i][j]=f[j][i]=0; //初始化
}
}
for(rg i=1;i<=m;++i){
rg x=qr()+1,y=qr()+1;
f[x][y]=f[y][x]=1; //邻接矩阵读边
}
if(n==0||n==2){puts("0");continue;}
if(m==0&&n&&n!=2){puts("1");continue;}//特判,这题有点卡细节
ans=1e9;
for(rg i=1;i<=n;++i){
for(rg j=1;j<=n;++j){
if(f[i][j]||i==j)continue; //注意两个相邻的点不可能通过割点不联通
S=i;T=j; solve(); //枚举源汇点
}
} if(ans==1e9)ans=n; //无论怎么割点图都联通,就输出n
printf("%d\n",ans);
}
return 0;
}
POJ 1966 Cable TV Network (最大流最小割)的更多相关文章
- POJ 1966 Cable TV Network
Cable TV Network Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 4702 Accepted: 2173 ...
- POJ 1966 Cable TV Network(顶点连通度的求解)
Cable TV Network Time Limit: 1000MS Memory Limit: 30000K Total Submissi ...
- POJ 1966 Cable TV NETWORK(网络流-最小点割集)
Cable TV NETWORK The interconnection of the relays in a cable TV net ...
- POJ 1966 Cable TV Network 【经典最小割问题】
Description n个点的无向图,问最少删掉几个点,使得图不连通 n<=50 m也许可以到完全图? Solution 最少,割点,不连通,可以想到最小割. 发现,图不连通,必然存在两个点不 ...
- POJ 1966 Cable TV Network (点连通度)【最小割】
<题目链接> 题目大意: 给定一个无向图,求点连通度,即最少去掉多少个点使得图不连通. 解题分析: 解决点连通度和边连通度的一类方法总结见 >>> 本题是求点连通度, ...
- POJ 1966 Cable TV Network (无向图点连通度)
[题意]给出一个由n个点,m条边组成的无向图.求最少去掉多少点才能使得图中存在两点,它们之间不连通. [思路]回想一下s->t的最小点割,就是去掉多少个点能使得s.t不连通.那么求点连通度就枚举 ...
- POJ 1966 Cable TV Network (算竞进阶习题)
拆点+网络流 拆点建图应该是很常见的套路了..一张无向图不联通,那么肯定有两个点不联通,但是我们不知道这两个点是什么. 所以我们枚举所有点,并把每个点拆成入点和出点,每次把枚举的两个点的入点作为s和t ...
- poj 1966 Cable TV Network 顶点连通度
题目链接 给一个图, n个点m条边, 求至少去掉多少个点可以使得图不再联通.随便指定一个点为源点, 枚举其他点为汇点的情况, 跑网络流, 求其中最小的情况. 如果最后ans为inf, 说明是一个完全图 ...
- POJ - 1966 Cable TV Network (最大流求点连通度)
题意:求一个无向图的点连通度.点联通度是指,一张图最少删掉几个点使该图不连通:若本身是非连通图,则点连通度为0. 分析:无向图的点连通度可以转化为最大流解决.方法是:1.任意选择一个点作为源点:2.枚 ...
随机推荐
- 清理docker 容器下面的log
1. docker info 找到docker root dir 2. go to /var/lib/docker 3. constainers 下面有每个容器的文件夹,-json.log 结尾的为L ...
- 点云网格化算法---MPA
MPA网格化算法思路 第一步:初始化一个种子三角面.(随机选点,基于该点进行临近搜索到第二点:在基于该线段中点临近搜索到第三点) 图1 第二步:在种子三角面的基础上,进行面片的扩充,利用边的中点进行临 ...
- 一个蒟蒻的解题过程记录——洛谷P1003 铺地毯
这到题算是我“火线回归”后码的第一道题,病好了心情不错,发篇博客分享一下 目录: ·题目描述 ·题目分析 ·解题思路 ·代码实现 ·总结 ·题目描述: 为了准备一场特殊的颁奖典礼,组织者在会场的一片矩 ...
- expression,statement,definition ,identifier(symbol) ,literal(字面量) 术语
expression: an expression evaluates to a value only statement: a statement containing executable cod ...
- Python学习之==>函数
一.函数是什么: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需要调用函数名就行. 二.函数的作用: 1.简化代码 2.提高代码的复用性 3.代码可扩展 三.定义函数: ...
- 用JS实现移动的窗口
https://blog.csdn.net/iteye_21064/article/details/81496640 用JS实现移动的窗口 2007年09月06日 23:23:00 阅读数:3 很简单 ...
- robot framework python3环境下学习笔记(1)——安装robot framework
安装环境:win10 64位,python3.6 1,安装robot framework pip install robotframework 2,安装wxPython pip install wxP ...
- 【HANA系列】SAP HANA ODBC error due to mismatch of version
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA ODBC er ...
- 第四周课程总结&第二次实验报告
实验二 Java简单类与对象 实验目的 掌握类的定义,熟悉属性.构造函数.方法的作用,掌握用类作为类型声明变量和方法返回值: 理解类和对象的区别,掌握构造函数的使用,熟悉通过对象名引用实例的方法和属性 ...
- LINUX “软链接”和“硬链接”的区别
今天在知乎上看到一篇十分有趣的问题: 如何评价微软高级工程师痴迷于soft link这一linux常见概念? 虽然又是知名撕逼王曾某的撕逼帖,但是我还是想就题目中链接的问题简单地讲讲. 什么是链接? ...