zoukankan      html  css  js  c++  java
  • poj 1087 A Plug for UNIX(二分匹配)

    题意:在一个房间里有N种插座和使用M种插座的电器,,这M种插座有些在现有的插座中不包含,不过可以通过适配器来转化,有K种类型的适配器来转化,让你求最少会有多少电器没法使用插座。

    思路:最大二分匹配。即求出最多有多少电器有相应的插座,然后用M减去就是所求,不过建图有点难想,我也是看了别人的解题报告才明白的。将电器和相应的插座类型连接起来,将能相互转化的插座连接起来,然后将不能直接使用N种插座而通过适配器的转换就能用的电器和插座连起来,然后就是求M种电器和N种插座的最大匹配了。呃,其实看到很多博客都是用最大流做的,原本这题也是在最大流的练习中找到的,但是我发现最大匹配更好理解,而且二分匹配加上源点和汇点就能转化成最大流。

    代码:

    View Code
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <string>
    #define  N 505
    using namespace std ;
    
    map<string , int>p ;
    int mp[N][N] ;
    int n , m , k , nx ;
    int f[N] , d[N] ;
    
    int dfs( int x )
    {
        int i ;
    
        for ( i = m + 1; i <= m + nx ; i++ )
        {
            if ( !f[i] && mp[x][i] )
            {
                f[i] = 1 ;
                if ( !d[i] || dfs( d[i] ))
                {
                    d[i] = x ;
                    return 1 ;
                }
            }
        }
        return 0 ;
    }
    //二分匹配模板
    int floyd( )
    {
        int i , sum ;
        sum = 0 ;
        memset( d , 0 , sizeof ( d ));
        for ( i = 1 ; i <= m ; i++ )
        {
            memset( f , 0 , sizeof ( f ));
            if ( dfs( i ))
            sum++;
        }
        return sum ;
    }
    
    int main()
    {
        int i , j , t ;
        string str1 , str2 ;
    
        //freopen("input.txt" , "r" , stdin );
        //输入N种插座
        scanf ( "%d" , &n ) ;
        p.clear();
        nx = n ;
        for ( i = 1 ; i <= n ; i++ )
        {
            cin>>str1 ;
            p[str1] = i ;
        }
        
        //输入M种电器
        scanf ( "%d" , &m );
        for ( i = 1 ; i <= m ; i++ )
        {
            cin>>str1>>str2 ;
            if ( p[str2] != 0 )
            {
                int x = p[str2] ;
                mp[i][x+m] = 1 ;
            }
            else
            {
                n++ ;
                p[str2] = n ;
                mp[i][n+m] = 1 ;
            }
        }
        
        //输入K种转化关系
        scanf ( "%d" , &k );
        for ( i = 1 ; i <= k ; i++ )
        {
            cin>>str1>>str2 ;
            if ( p[str1] == 0 )
            {
                n++ ;
                p[str1] = n ;
            }
            if ( p[str2] == 0 )
            {
                n++ ;
                p[str2] = n ;
            }
            mp[p[str1]+m][p[str2]+m] = 1 ;
        }
        
        //将通过适配器可以使用原来N种插座的电器连起来。
        for ( i = 1 ; i <= m + n ; i++ )
        for ( j = 1 ; j <= m + n ; j++ )
        for ( t = 1 ; t <= m + n ; t++ )
        if ( mp[j][i] && mp[i][t] && !mp[j][t] )
        mp[j][t] = 1 ;
        
        int flow = floyd( );
        printf ( "%d\n" , m - flow ) ;
        return 0;
    }
  • 相关阅读:
    函数二 10
    函数初识 09
    文件操作 08
    数据类型的补充 day07
    小数据池 深浅copy 集合
    python Mysql 多条件查询
    ElasticSearch Python 基本操作
    用PyInstaller把Python代码打包成单个独立的exe可执行文件
    python 编译EXE文件
    Git 创建新分支检查分支
  • 原文地址:https://www.cnblogs.com/misty1/p/2689647.html
Copyright © 2011-2022 走看看