【bzoj1143】 CTSC2008祭祀river 二分图匹配

论坛 期权论坛 脚本     
匿名技术用户   2020-12-30 22:10   50   0

貌似是我想少了,二分图不止只有最大匹配,先写一些结论吧,等着总结一下。

参考:http://endlesscount.blog.163.com/blog/static/821197872012622103810976/

二分图最小点覆盖(每条边至少一个顶点在集合里)=最大匹配

二分图最小边覆盖(每个点至少连一条边)=二分图点数-最大匹配

证明:考虑最大匹配后,每个未匹配的点连出一条边,即为最小边覆盖=二分图点数-2*最大匹配+最大匹配=二分图点数-最大匹配。

二分图最大独立集(点两两无边)=二分图点数-最小点覆盖

有向无环图最小不相交路径覆盖

把原图中的每个点V拆成Vx和Vy,如果有一条有向边A->B,那么就加边Ax-By。这样就得到了一个二分图,最小路径覆盖=原图的节点数-新图最大匹配。
简单证明:一开始每个点都独立的为一条路径,总共有n条不相交路径。我们每次在二分图里加一条边就相当于把两条路径合成了一条路径,因为路径之间不能有公共点,所以加的边之间也不能有公共点,这就是匹配的定义。所以有:最小路径覆盖=原图的节点数-新图最大匹配。
有向无环图最小可相交路径覆盖
先floyd求出连通性后,最小不相交路径覆盖。

这道题是裸的二分图最大独立集,对于原图的点x、y,如果联通,则从ax向by连一条边,最后要求选中的点之间没有连边即求最大独立集。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 110

using namespace std;

int a[maxn][maxn],lk[maxn],f[maxn][maxn];
bool vis[maxn];
int n,m;

bool find(int x)
{
 for (int i=1;i<=n;i++)
   if (a[x][i] && !vis[i])
   {
    vis[i]=1;
    if (!lk[i] || find(lk[i]))
    {
     lk[i]=x;
     return 1;
    }
   }
 return 0;
}

int main()
{
 scanf("%d%d",&n,&m);
 for (int i=1;i<=m;i++)
 {
  int x,y;
  scanf("%d%d",&x,&y);
  f[x][y]=1;
 }
 for (int k=1;k<=n;k++)
   for (int i=1;i<=n;i++)
     for (int j=1;j<=n;j++)
       f[i][j]|=f[i][k]&&f[k][j];
 for (int i=1;i<=n;i++)
   for (int j=1;j<=n;j++)
     if (f[i][j] && i!=j) a[i][j]=1;
 int ans=n;
 for (int i=1;i<=n;i++)
 {
  memset(vis,0,sizeof(vis));
  if (find(i)) ans--;
 }
 printf("%d\n",ans);
 return 0;
}


分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP