zoukankan      html  css  js  c++  java
  • ural Mosaic(强连通分支)

    题意:幼儿园里有N个盒子,每个盒子有一种颜色,每个盒子中可以装M个与盒子颜色相同的拼图,但是现在有些孩子将拼图放错了盒子,幼儿园老师要将放错的拼图放到正确的盒子里,她每次可以拿一块拼图从这个盒子到另一个盒子,也可以什么都不拿都另一个盒子,问这个老师最少要移动多少次手才能整理好这些拼图。

    思路:求强连通分支。首先,在同一个强连通分支里的盒子之间是可以互换的,即颜色A的拼图放到了颜色B的盒子了,那么一定可以从颜色B的盒子里取出A然后放回颜色为A的盒子里,然后从A盒子了取出颜色不为A的拼图放回正确的盒子里,所以最少移动的次数就是放错拼图的个数。如果不是一个强连通分支,那么在整理完这个强连通分支里的盒子后,一定会空手到另一个强连通分支去,最少的移动次数是:放错的拼图数+(强连通分支数-1)。另外还要考虑的是,如果这个盒子的拼图都是正确,那么这个盒子就不能加入图中。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <math.h>
    #include <stack>
    #include <vector>
    #include <map>
    #define  N 53
    #define  M 505
    using namespace std ;
    
    bool mp[M][M] ;
    int dfn[M] , low[M] ;
    bool used[M] , vist[M] , f[M] ;
    int id , ans , cnt , n , m ;
    stack<int>q ;
    
    void init()
    {
        memset( mp , false , sizeof( mp )) ;
        memset( dfn , 0 , sizeof ( dfn )) ;
        memset( low , 0 , sizeof ( low )) ;
        memset( used , false , sizeof( used ));
        memset( vist , false , sizeof ( vist )) ;
        memset( f , false , sizeof ( f )) ;
        id = cnt = ans = 0 ;
        while( !q.empty()) q.pop();
    }
    
    void Tarjan( int x )
    {
        dfn[x] = low[x] = ++id ;
        used[x] = vist[x] = true ;
        q.push( x ) ;
    
        for ( int i = 1 ; i <= n ; i++ )
        {
            if ( mp[x][i] )
            {
                if ( !used[i] )
                {
                    Tarjan( i ) ;
                    low[x] = min( low[x] , low[i] ) ;
                }
                else if ( vist[i] )
                {
                    low[x] = min( low[x] , dfn[i] ) ;
                }
            }
        }
        if ( dfn[x] == low[x] )
        {
            ans++ ;
            int u ;
            do
            {
                u = q.top() ;
                q.pop();
                vist[u] = false ;
            }while( u != x ) ;
        }
    }
    
    int main()
    {
        int i , j , x ;
    
        while ( scanf ( "%d%d" , &n , &m ) != EOF )
        {
            init() ;
            for ( i = 1 ; i <= n ; i++ )
            {
                for ( j = 1 ; j <= m ; j++ )
                {
                    scanf ( "%d" , &x ) ;
                    if ( x != i )
                    {
                        mp[x][i] = true ;
                        f[i] = true ;
                        cnt++ ;
                    }
                }
            }
    
            /*for ( i = 1 ; i <= n ; i++ )
            {
                for ( j = 1 ; j <= n ; j++ )
                cout<<mp[i][j]<<" ";
                cout<<endl ;
            }*/
            for ( i = 1 ; i <= n ; i++ )
            if ( !dfn[i] && f[i] )
            Tarjan( i ) ;
    
            //cout<<ans<<endl ;
            cnt = cnt + max( ans - 1 , 0 );
    
            cout<<cnt<<endl ;
        }
        return 0 ;
    }
  • 相关阅读:
    学习TextKit框架(上)
    UITextView -- 基础备忘
    Quartz2D 备忘 + 学习
    CALayer -- 备忘
    NSURLSession -- 实际开发中运用
    NSURLSession -- 备忘
    Collection View 自定义布局(custom flow layout)
    CSS中一个冒号和两个冒号之间区别
    Chrome插件LiveStyle结合Sublime Text编辑器实现高效可视化开发
    Taking Advantage of HTML5 and CSS3 with Modernizr
  • 原文地址:https://www.cnblogs.com/misty1/p/2875340.html
Copyright © 2011-2022 走看看