bzoj1143-最小链覆盖&偏序集定理&二分图-祭祀river

http://www.lydsy.com/JudgeOnline/problem.php?id=1143
据说是南宁m题?
关键是问题的转化,然后就是一个板子。
最大反链覆盖->最小链覆盖。
链就是可以到达的点(任意两个,u可以到达v或者v可以到达u)
最小链覆盖->最小路径覆盖(可交叉)
另外。最近才发现的,二分图的求解往往是隐式拆点了。
看着没有拆,可是求解的过程 用的linker和used,是已经当成两个点处理的。

/**************************************************************
    Problem: 1143
    User: abcd156555
    Language: C++
    Result: Accepted
    Time:40 ms
    Memory:1444 kb
****************************************************************/

#include <bits/stdc++.h>
using namespace std;
/* 这道题是求最小链覆盖。
啥是链呢,就是一个数组里面的数,每一个都能到达另一个(可能并不能相互到达)
但是可以到达,就叫最小链覆盖。
那么这道题就是最大反链覆盖了。
根据偏序集定理,最大反链覆盖就是 最小链覆盖。
(这个是,有证明的。)
那么我们就直接求 最小链覆盖就好了
那么,如何求最小链覆盖呢。
说实话,我也不会。但是我会百度。
有人说可以最小可相交路径覆盖 就好了
因为 最小链的意思就是 这些点的数目尽可能的小,
并且他们之间的路径 可以经过所有的点。
这些最小链是可以相交的。
*/
const int maxn=200;
int mp[maxn][maxn];
int linker[maxn];
bool used[maxn];
int m,n;
bool dfs(int u){
      for(int v=1;v<=m;v++){
          if(mp[u][v]&&!used[v]){
              used[v]=true;
              if(linker[v]==-1||dfs(linker[v])){
                 linker[v]=u;
                 return true;
              }
          }
      }
      return false;
}
int main()
{   int a,b;
    scanf("%d%d",&m,&n);
      for(int i=0;i<n;i++){
          scanf("%d%d",&a,&b);
          mp[a][b]=1;
      }
      for(int k=1;k<=m;k++){
          for(int i=1;i<=m;i++){
             for(int j=1;j<=m;j++)
                if(mp[i][k]&&mp[k][j])
                mp[i][j]=1;
          }
      }
      int res=0;
      memset(linker,-1,sizeof(linker));
      for(int i=1;i<=m;i++){
          memset(used,0,sizeof(used));
          if(dfs(i))
            res++;
      }
      printf("%d\n",m-res);//最小路径覆盖就是顶点数-匹配数
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值