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;
    }
    

      

  • 相关阅读:
    求职简历撰写要点和模板分享
    find命令
    MD5Init-MD5Update-MD5Final
    Linux find命令详解
    Linux进程KILL不掉的原因
    Linux操作系统的内存使用方法详细解析
    Lsof命令详解
    为什么ps中CPU占用率会有超出%100的现象?
    第12课 经典问题解析一
    第11课 新型的类型转换
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1143.html
Copyright © 2011-2022 走看看