zoukankan      html  css  js  c++  java
  • ural Two Rounds(分组背包)

    题意:乌拉尔锦标赛分为两轮,每轮有N道题,总共有2*N道题,但是在这些题中,有些题目有相似性,这样的题目是不允许放在同一轮里的,题目要求给出合理的题目分组来。

    分析:刚开始想用BFS搜的,在搜的过程中进行染色,但是最后放弃了这个思路,因为这个图极有可能是不连通的,怎样确定每个连通分支起始点的颜色才能找到一个合理的分组来就成为解题的关键,但是这个却没有一个准确的规律可循,所以只能用分组背包。其实就是先进行一遍dfs的深搜,将每个连通分支的点都分为两种颜色,将每个连通分支作为一组,然后进行dp求解。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #define  N 103
    using namespace std ;
    
    vector<int>p[N] ;
    int mp[N][N] , f[N] ;
    int s[N] , num1[N] , num2[N] ;
    int n , m ;
    
    void init()
    {
        memset( mp , 0 , sizeof( mp )) ;
        memset( num1 , 0 , sizeof ( num1 )) ;
        memset( num2 , 0 , sizeof ( num2 )) ;
        memset( f , 0 , sizeof ( f )) ;
        memset( s , 0 , sizeof( s )) ;
        for ( int i = 0 ; i <= 2 * n ; i++ )
        p[i].clear() ;
    }
    
    bool dfs( int x , int id )
    {
        if ( f[x] )
        {
            if ( f[x] == id )
            return true ;
            return false ;
        }
        f[x] = id ;
        if ( id > 0 ) num1[id]++ ;
        else
        num2[-id]++ ;
    
        for ( int i = 0 ; i < p[x].size() ; i++ )
        {
            if ( !dfs( p[x][i] , -id ))
            return false ;
        }
        return true ;
    }
    
    int main()
    {
        int i , j , x , y , k ;
    
        while ( scanf ( "%d%d" , &n , &m ) != EOF )
        {
            init() ;
    
            for ( i = 1 ; i <= m ; i++ )
            {
                scanf ( "%d%d" , &x , &y ) ;
                p[x].push_back( y ) ;
                p[y].push_back( x ) ;
            }
            x = 0 ;
            for ( i = 1 ; i <= 2 * n ; i++ )
            {
                if ( !f[i] )
                {
                   if ( !dfs( i , ++x ) )
                   break ;
                }
            }
            if ( i <= 2 * n )
            {
                printf ( "IMPOSSIBLE\n" ) ;
                continue ;
            }
    
            mp[0][0] = 1 ;
            for ( i = 0 ; i <= x ; i++ )
            {
                for ( j = 0 ; j <= n ; j++ )
                {
                    if ( mp[i][j] == 0 )
                    continue;
                    mp[i+1][j+num1[i+1]] = 1 ;
                    mp[i+1][j+num2[i+1]] = -1 ;
                }
            }
    
            if( mp[x][n] == 0 )
            {
                printf ( "IMPOSSIBLE\n" ) ;
            }
            else
            {
                k = n ;
                for ( i = x ; i > 0 ; i-- )
                {
                    s[i] = mp[i][k] ;
                    if ( mp[i][k] > 0 )
                    k -= num1[i] ;
                    else
                    k -= num2[i] ;
                }
    
                for ( i = 1 ; i <= 2 * n ; i++ )
                {
                    if ( ( f[i] > 0 && s[f[i]] > 0 ) || ( f[i] < 0 && s[-f[i]] < 0 ))
                    printf ( "%d " , i ) ;
                }
                printf ( "\n" ) ;
                for ( i = 1 ; i <= 2 * n ; i++ )
                {
                    if (!( f[i] > 0 && s[f[i]] == 1 ) && !( f[i] < 0 && s[-f[i]] == -1 ))
                    printf ( "%d " , i ) ;
                }
                printf ( "\n" ) ;
            }
        }
        return 0 ;
    }
  • 相关阅读:
    linux 命令学习
    反编译学习一:Mac下使用dex2jar
    如何删除你的MacOS上的旧版本Java
    使用screen 遇到的多窗口
    dede简略标题调用标签
    JQ实现导航滚动到指定位置变色,并置顶
    JQ实现当前页面导航加效果(栏目页有效)
    wordpress首页调用指定分类下的文章
    作业1#python用列表实现多用户登录,并有三次机会
    python数据类型之间的转换
  • 原文地址:https://www.cnblogs.com/misty1/p/2879506.html
Copyright © 2011-2022 走看看