zoukankan      html  css  js  c++  java
  • BZOJ1143 [CTSC2008]祭祀river 二分图匹配 最小链覆盖

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ1143


    题意概括

      给出一个有向图。求最小链覆盖。


    题解

      首先说两个概念:

        链:一条链是一些点的集合,链上任意两个点x, y,满足要么 x 能到达 y ,要么 y 能到达 x 。

        反链:一条反链是一些点的集合,链上任意两个点x, y,满足 x 不能到达 y,且 y 也不能到达 x。

      这题就是求最长反链长度。

      有两个定理:

      最长反链长度 = 最小链覆盖

      最长链长度 = 最小反链覆盖

      这题明显可以使用第一个。

      那么只需要floyd跑一跑,然后二分图匹配就可以了。

      代码比较短。


    代码

    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int N=100+5,N2=N*2;
    int n,m,match[N2];
    bool g[N][N],g2[N2][N2],vis[N2];
    bool dfs(int x){
    	for (int i=1;i<=n;i++){
    		int y=i+n;
    		if (!vis[y]&&g2[x][y]){
    			vis[y]=1;
    			if (match[y]==-1||dfs(match[y])){
    				match[y]=x;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int main(){
    	memset(g,0,sizeof g);
    	memset(g2,0,sizeof g2);
    	scanf("%d%d",&n,&m);
    	for (int i=1,a,b;i<=m;i++){
    		scanf("%d%d",&a,&b);
    		g[a][b]=1;
    	}
    	for (int k=1;k<=n;k++)
    		for (int i=1;i<=n;i++)
    			for (int j=1;j<=n;j++)
    				g[i][j]=g[i][j]||(g[i][k]&&g[k][j]);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++)
    			if (g[i][j])
    				g2[i][j+n]=1;
    	int cnt=0;
    	memset(match,-1,sizeof match);
    	for (int i=1;i<=n;i++){
    		memset(vis,0,sizeof vis);
    		if (dfs(i))
    			cnt++;
    	}
    	printf("%d
    ",n-cnt);
    	return 0;
    }
    

      

  • 相关阅读:
    windows p12(pfx)个人证书安装过程
    OpenSSL库验证PKCS7签名
    Crypto库实现PKCS7签名与签名验证
    windows 系统中打开一个数字证书所经历的过程
    DBA不可不知的操作系统内核参数
    MySQL大表优化方案
    深入浅出Cache
    Git Stash用法
    Git服务器搭建全过程分步详解
    laravel 5.1 性能优化对比
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1143.html
Copyright © 2011-2022 走看看