首页 > 其他分享 >1.1.3.4 最小割之建图实战、费用流基本概念

1.1.3.4 最小割之建图实战、费用流基本概念

时间:2024-03-11 18:25:08浏览次数:31  
标签:1.1 int 源点 flow 最小 汇点 3.4 edge 割之建图

1.1.3.4 最小割之建图实战、费用流基本概念

最小割之建图实战

381. 有线电视网络

Problem

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

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

Solution

最小割模型的通用分析方式:

  1. 通过原图构造一个流网络
  2. 证明流网络的割集合和原题要求的集合一一对应
  3. 可以设置一个“简单割”的定义辅助自己证明

若无向图不连通,则图中至少必有两个点不连通,因此可以枚举最终不连通的点,我们取源点 S 和汇点 T,(注意:源点与汇点是枚举出来的,不是固定的)

题目转化为在剩余 n−2

个节点中最少去掉多少个,可以使 S 和 T 不连通。

注意:S 和 T 不能直接相连,否则不可能达到要求。 (比如三角形那种图)

在每次枚举的结果中取最小值就是本题的答案。
建图

考虑把删点转化为删边,与最小割联系起来

通过拆点我们可以把点限制变成边限制,将每个点拆成 入点 -> 出点 (这里我们把一个点的入点到出点的边叫做点内部的边,从其他点连过来的边叫做点外部的边)

这样把找割点的操作就变成了找割边的操作了。

因为我们只能去掉点,而不能去掉边,所以我们要使流网络的割边出现在点的内部,即拆点构成的边,而不能出现在点外部。

Tips:我们可以把所有不想让他出现在割边集里的边的容量设置为正无穷

因此我们可以将内部边的容量设为1,外部边的容量设为正无穷。

下面证明一下这种建图的正确性:

这里设定简单割为割边只包含内部边,不包含外部边。

如果一开始源点到汇点之间是没有边的话(如果有边就必不能令其孤立了,要把两个点都删掉),则从源点到汇点的路径必然会经过点的内部,即必然会经过容量为有限的边,这样从源点到汇点流过的可行流一定是有限值,最大流就一定是有限值,根据最小割=最大流,则最小割也是有限值,这样的最小割就必定是个简单割,即只包含点内部的边。最小的简单割一定是最小割。

这样的,所有简单割的集合就可以对应于本题中你想要删掉点的集合,因此从源点到汇点做一遍最小割,就是最小的需要删掉的点数。

证明简单割与要删掉的点的点割集存在一一对应的关系:

简单割 => 点割集

因为我们通过简单割求出的割边都是点内部的边,当我们把简单割里的边全删掉后,源点和汇点则不会联通了,这些构成“内部边”的点的集合就是点割集。

下面用反证法证明上面构造出来的点割集一定是符合题意的要删掉的点:

假设上面构造出来的点割集不符合题意,即把上面所有的点删掉,在原图里依然存在从源点到达汇点的路径,说明在原图中,存在一条不经过我们构造出来的点割集里的点的路径即不经过“点内部的边”,依然能从源点到达汇点,对应到流网络里则是存在一条从源点到汇点的不经过割边的路径,则说明源点与汇点在一个集合里,说明这不是一个割,与前提矛盾。因此反证得证。

点割集 => 简单割

这里的点割集指的是“极小点割集”

构造简单割的方法:

从源点开始dfs一遍,若经过点割集里的点,则停下不往前搜,若不是则往前搜,每次把搜到的点打个标记,这样标记了的点就是S集合,没有标记的点就是T集合,构成一个简单割C[S,T]

因此我们可以证出简单割与割点集存在一一对应的关系。
考虑数量关系

由于我们建边的时候把入点到出点的边的容量设为1,则得到的简单割的割边和就是选到的点的数量,则可以得到
割点集的点的数量 = 简单割的割的容量和 ,因此
\(最小割点集 = 最小割\)

总结

枚举源点与汇点,

源点枚举的是点的出点,汇点枚举的是点的入点

跑一遍dinic,在每次枚举的时候取更小的值即可。

但如果仅仅这样的话,我们发现网络流中的最小割与原问题的解不是一一对应的。

这是因为最小割中一定不包括源点和汇点,

但是只要原问题的解最后余下两个点以上,这种方案已经包括在最小割中了。
所以我们分别考虑最后只余下一个点和零个点的情况,

一个点的话,图还连通,不符题意。
零个点的话,符合题意,需要割掉的点数为n。
#include<bits/stdc++.h>
using namespace std;
const int MX_N=5100,MX_M=51000;
const int INF=0x3f3f3f3f;
struct node{
    int next,to,w;
}edge[MX_M<<1];
int head[MX_N]={0},edge_cnt=0;
inline void Add(int x,int y,int w){
    node &i=edge[edge_cnt];
    i.to=y,i.w=w,i.next=head[x];
    head[x]=edge_cnt++;
}
inline void add(int x,int y,int w){
    Add(x,y,w),Add(y,x,0);
}
int cur[MX_N]={0},dist[MX_N]={0};
int s=0,t=MX_N-1;
bool bfs(){
    for(int i=0;i<MX_N;i++)  cur[i]=head[i],dist[i]=-1;
    queue<int > qu;qu.push(s);
    dist[s]=0;
    while(!qu.empty()){
        int now=qu.front();qu.pop();
        for(int i=head[now];~i;i=edge[i].next){
            int to=edge[i].to,w=edge[i].w;
            if(dist[to]==-1&&w){
                qu.push(to);
                dist[to]=dist[now]+1;
            }
        }
    }
    return dist[t]!=-1;
}
int dfs(int now,int flow){
    if(now==t)  return flow;
    int left=flow;
    for(int &i=cur[now];~i;i=edge[i].next){
        int to=edge[i].to,w=edge[i].w;
        if(dist[to]==dist[now]+1&&w){
            int cur_flow=dfs(to,min(left,w));
            left-=cur_flow;
            edge[i].w-=cur_flow;
            edge[i^1].w+=cur_flow;
            if(left==0)  break;
        }
    }
    if(left==flow)  dist[now]=-1;
    return flow-left;
}
int dinic(){
    int sum=0;
    while(bfs())  sum+=dfs(s,INF);
    return sum;
}
inline void init(){
    edge_cnt=0;memset(head,-1,sizeof(head));
}
inline void build(){
    for(int i=0;i<edge_cnt;i+=2){
        edge[i].w+=edge[i^1].w;
        edge[i^1].w=0;
    }
}
signed main()
{
    char c;
    int n,m;
    while(scanf("%d%d",&n,&m)==2) {
        init();
        for(int i=1;i<=m;i++) {
            int x,y;
            cin>>c;
            scanf("%d,%d",&x,&y);x++,y++;
            cin>>c;
            add(x+n,y,INF);
            add(y+n,x,INF);
        }
        for(int i=1;i<=n;i++)  add(i,i+n,1);
        int minn=n;
        for(int S=1;S<=n;S++){
            for(int T=S+1;T<=n;T++){
                if(S==T)  continue ;
                s=S+n,t=T;
                minn=min(minn,dinic());
                build();
            }
        }
        printf("%d\n",minn);
    }
    return 0;
}

标签:1.1,int,源点,flow,最小,汇点,3.4,edge,割之建图
From: https://www.cnblogs.com/DaiFu/p/18066726

相关文章

  • 上周热点回顾(3.4-3.10)
    热点随笔:· 这波操作看麻了!十亿行数据,从71s到1.7s的优化之路。 (why技术)· 开源.NET8.0小项目伪微服务框架(分布式、EFCore、Redis、RabbitMQ、Mysql等) (aehyok)· C#/.NET/.NETCore优秀项目和框架2024年2月简报 (追逐时光者)· AI应用开发之路-准备:发起一个开源小项目D......
  • SMU Winter 2024 div2 ptlks的周报Week 5(3.4-3.10)
    维护子树的全部子树的权值和时,需要用到树的DFS序列,树的每个子树都对应DFS序列中的连续一段黄金树影题意:给定一棵树及每个节点的权值,给定一组操作,输入1ax,表示节点a权值加上x;输入2a,表示询问节点a的子树权值和(包含a)。考虑到树的DFS序列,则问题转变为对某个序列维护区间和以......
  • 3.4-3.10周报
    周二天梯训练赛天梯选拔赛一A这个题就是每次看到'.',就在它后面放一串英文字符"xixixixi."L其实就是看完整过了多少个视频,以及剩下的那个视频有没有播放到第m秒。J这个题wa了六发,好离谱,题读错了,其实就是每次都减去当前这个数字里任意一个数位,那我们就能有一个贪心思路,每次......
  • Sealos 给全体用户献上开春福利!降价 33.5%~73.4%
    Sealos经过23年一年的迭代,获得了用户的广泛好评,注册用户已破十万,应用数量也突破一万,24年的工作重心会放在价格上,在我们不死掉的情况下尽可能为用户谋福利!好消息是Sealos与各大云厂商深度合作,加上Sealos本身的多租户云版拼多多的业务模式,终于能把价格打下来了!本次我们同......
  • 3.4格力
    3.4格力赣州自我介绍讲解一下项目问题小程序是否上线?答:小程序是本地部署。还未上线,但是会上线的。Vue的了解多少?答:对Vue了解的不多,大多数会用的程度。Vue的生命周期和声明是怎么样的?讲解一下答:这个不是很清楚,对Vue了解的不多,可能使用多一点。Java的......
  • 记录零基础的行人重识别---2024.3.4 第一天
    本人研一小白一枚,老师给定的研究方向为行人重识别的方向,最近在知乎上面看到了郑哲东大佬以及他们悉尼科技大学小组曾经写的知乎帖子https://zhuanlan.zhihu.com/p/50387521,随手也附上他们的GitHub项目链接https://github.com/layumi/Person_reID_baseline_pytorch/tree/master/......
  • 3.4日Android studio
      今天在进行Androidstudio开发时,虚拟机不能使用了,在网上找了很多的方法,才能使用1.检查当前电脑是否开启虚拟化技术,开启方式重启电脑进入BIOS界面,找到VirtualTechnology或VT-x字样,设置为enable2.检查当前AndroidStudio关联的SDK是否下载插件HAXM,打开Settings界面,搜索SDK,在......
  • 云原生周刊:CNCF 宣布 Falco 毕业|2024.3.4
    开源项目推荐ldap-operator用于部署和管理LDAP目录的KubernetesOperator。UpdatecliUpdatecli是一个用于应用文件更新策略的工具。每个应用程序“运行”时都设计为可在任何地方使用,它会检测是否需要使用自定义策略更新值,然后根据该策略应用更改。AlazAlaz是一个开源D......
  • 关于SAP-APP机器-R3trans -d报错-R3trans: /lib64/libstdc++.so.6: version `GLIBCXX_
    在SAP-应用-APP-机器上执行如下命令报错awpxxx03:prdadm270>R3trans-dR3trans:/lib64/libstdc++.so.6:version`GLIBCXX_3.4.26'notfound(requiredbyR3trans) 其实之前,使用过一种方法解决这个问题,可以参考笔者另一篇文章《关于Redhat-Linux中-compat-sap-c++的说......
  • 3.4 STL 学习笔记一
    这是初次学习STL的相关知识。可能之后还会补充笔记。STL是提高C++编写效率的一个利器1.#includevector是变长数组,支持随机访问,不支持在任意位置O(1)插入。为了保证效率,元素的增删一般应该在末尾进行。1.1声明include//头文件vectora;//相当于一个长度变化的int数组......