• 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 ;
    }
  • 相关阅读:
    LeetCode_145.二叉树的后序遍历
    LeetCode_144.二叉树的前序遍历
    LeetCode_142.环形链表 II
    LeetCode_141.环形链表
    LINQ查询表达式---------select子句
    LINQ查询表达式---------where子句
    LINQ查询表达式---------from子句
    System.InvalidOperationException: 未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序。
    Directory.GetFiles()获取多个类型格式的文件
    System.Exception: ORA-12541: TNS: 无监听程序
  • 原文地址:https://www.cnblogs.com/misty1/p/2879506.html
Copyright © 2020-2023  润新知