二分图最大匹配

文章目录

  • 二分图
    • 定义
    • 充分必要条件
    • 性质
    • 判定
  • 二分图最大匹配
    • 定义
  • 增广路
    • 概念
    • 特点
  • Dinic算法
    • 最小点覆盖
      • 定义
    • 最小路径覆盖
      • 定义
      • 详细
    • 最大独立集
      • 定义

二分图

定义

图论中的一种特殊的模型。设G=(V,E)是一个无向图,如果顶点V可以分割为两个不想交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G是一个二分图。

充分必要条件

G至少有两个顶点,且其所有回路长度均为偶数。

性质

最大匹配数=最小覆盖数
二分图的独立数=顶点数-最大匹配数
最大匹配数=左边匹配点+右边匹配点
最小边覆盖=所有顶点数-最大匹配数=最大独立集
最小顶点覆盖就是用最少的点来覆盖所有的边

判定

传送门

二分图最大匹配

最大匹配可以用最大流或者匈牙利算法

定义

给定一个二分图G,在G的一个子图中,M的边集中的任何两条边都不依赖同一个顶点,则称为一个匹配。选择这样边数最大的子集称为图的最大匹配问题。如果一个匹配中,图中的每一个顶点都和图中某条边相关联,则称此匹配为完全匹配。

增广路

概念

交替路:从一个未匹配的点出发,依次经过未匹配的边、匹配边、未匹配边…
增广路:从一个未被匹配的点出发,走交替路,到达了一个未被匹配过的点,这条路叫做增广路。

特点

增广路有奇数条
路径上的点一定是一个在X上,一个在Y上,交替出现
起点和终点都是目前还没有配对的点
未匹配的数量比匹配的数量多1

Dinic算法

Dinic主要是建图,源点与左边所有点相连;汇点与右部所有点相连;左边与右边相连;容量都为1即可

模板题

#include 
#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f
using namespace std;
const int N=6e6+5;
struct node
{
    int v,cap,to;
}s[N];
int cnt,head[N],dis[N];
int a,t;///»ãµã
void add(int u,int v,int cap)
{
    s[cnt].v=v;
    s[cnt].cap=cap;
    s[cnt].to=head[u];
    head[u]=cnt++;
    s[cnt].v=u;
    s[cnt].cap=0;
    s[cnt].to=head[v];
    head[v]=cnt++;
}
bool bfs()
{
    queue<int>q;
    memset(dis,0,sizeof(dis));
    dis[a]=1;
    q.push(a);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int e=head[u];~e;e=s[e].to)
        {
            int v=s[e].v,cap=s[e].cap;
            if(!dis[v]&&cap>0)
            {
                dis[v]=dis[u]+1;
                q.push(v);
            }
        }
    }
    return dis[t]!=0;
}
int dfs(int u,int flow)
{
    int mm;
    if(u==t)
        return flow;
    for(int e=head[u];~e;e=s[e].to)
    {
        int v=s[e].v,cap=s[e].cap;
        if(cap>0&&dis[v]==dis[u]+1&&(mm=dfs(v,min(cap,flow))))
        {
            s[e].cap-=mm;
            s[e^1].cap+=mm;
            return mm;
        }
    }
    dis[u]=-1;
    return 0;
}
int dinic()
{
    int ans=0,tf;
    while(bfs())
    {
        while(tf=dfs(0,inf))//0±íʾԴµã
        {
            //printf("%d*\n",tf);
            ans+=tf;
        }
    }
    return ans;
}
void init()///³õʼ»¯
{
    cnt=0;
    memset(head,-1,sizeof(head));
}
int main()
{
    int n,m,p;
    init();
    scanf("%d%d%d",&n,&m,&p);
    a=0,t=n+m+1;
    for(int i=1;i<=n;i++){
    	add(a,i,1);
	}
	for(int i=1;i<=m;i++){
		add(i+n,t,1);
	}
    for(int i=1;i<=p;i++){
    	int u1,v1;
    	scanf("%d%d",&u1,&v1);
    	add(u1,n+v1,1);
	}
	printf("%d\n",dinic());   
    return 0;
}

最小点覆盖

定义

给定无向图G=(V,E),若点集x属于V满足:E中任意一条边至少有一个端点在X中,则称X为G的点覆盖。点数最小的点覆盖称为最小点覆盖。
最小顶点覆盖就是用最少的点来覆盖所有的边
最大匹配数=最小点覆盖数

POJ1325 Machine Schedule
POJ3041 Asteroids
POJ2226 Muddy Fields

最小路径覆盖

定义

给定有向图G=(V,E),设P是图G上若干点不相交的简单路径的集合,若每个点v属于V都存在于唯一一条P中的路径上,则P是G的一条路径覆盖。路径数量最少的路径覆盖称为最小路径覆盖。用MinPC(G)表示图G的最小路径覆盖数
有向无环图的最小路径覆盖问题可转化为二分图的最大匹配问题。给定有向无环图G=(V,E),设V={1,2,…,n},将点i属于V拆成xi、yi两个点,若(i,j)属于E,则连一条无向边(xi,yi)。得到二分图G’

详细

POJ2724 Purifying Machine
POJ3020 Antenna Placement

最大独立集

定义

选出一些顶点使得这些顶点两两不相邻,则这些点构成的集合称之为独立集。找出一个顶点包含数量最多的独立集称为最大独立集。
最小边覆盖=所有顶点数-最大匹配数=最大独立集

POJ1466 Girls and Boys
POJ3692 Kindergarten

你可能感兴趣的:(网络流)