• 1124. Mosaic


    1124. Mosaic

    Time limit: 0.25 second Memory limit: 64 MB
    There's no doubt that one of the most important and crucial things to do in this world is to bring up children. May be, if you study properly and reach good results at the competition you'll get a position of nanny in a kindergarten. But you are to get ready for it! Let's consider some problems that a nanny has to solve in a kindergarten.
    Everyone knows the game "Mosaic". Playing the game, one is to lay out pictures of different colored pieces. Let there be M different boxes and N mosaic pieces of each of the M colors. After playing the game children rarely put the pieces back to their boxes correctly so that the color of the box and the colors of its pirces would be the same. A nanny has to do that.
    Children have already put the mosaic pieces to the boxes but possibly not correctly. There are N pieces in each box. Some pieces (possibly all of them) are located in wrong boxes (i.e. boxes with pieces of a different color). Moving a hand once one can take a piece from one box to another or simply move the hand to another box. You may start from any box you like. The movement towards the first box is not taken into account. Find out the minimal number of movements one needs to put all the mosaic pieces to their boxes.

    Input

    The first line contains integers 2 ≤ M ≤ 500 (the number of colors) and 2 ≤ N ≤ 50 (the number of pieces of each color), Each of the next M lines contains Nnumbers in the range from 1 to M (the i+1-st line contains colors of pieces located in the i-th box). The numbers are separated with a space.

    Output

    the minimal possible number of hand movements that one has to make in order to take all the pieces to their boxes.

    Sample

    inputoutput
    4 3
    1 3 1
    2 3 3
    1 2 2
    4 4 4
    
    6
    
    Problem Author: Stanislav Vasilyev Problem Source: VI Ural State University Collegiate Programming Contest (21.10.2001)
    ***************************************************************************************
    求强连通的个数。
    ***************************************************************************************
     1 #include<iostream>
     2 #include<cstring>
     3 #include<string>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<stack>
     7 using namespace std;
     8 int low[1001];//low数组记录离i点最远的祖先,如果是他自己则返回一个连通分量;
     9 int dfn[1001];//记录本节点的编号
    10 bool  in[1001];//标记一节点是否在栈中
    11 bool side[1001][1001];//标记本箱子中不同的结点
    12 int ans,deep;
    13 bool  vis[1001];//标记是否访问过
    14 int n,m,num[1001];
    15 stack<int>stk;
    16 int sd;
    17 int min1(int a,int b)
    18 {
    19     return a>b?b:a;
    20 }
    21 void tarjan(int x)
    22  {
    23      low[x]=dfn[x]=deep++;
    24      vis[x]=true;
    25      stk.push(x);
    26      in[x]=true;
    27     for(int iv=1;iv<=n;iv++)
    28      {
    29          if(side[x][iv]==false)
    30           continue;
    31          if(!vis[iv])
    32            {
    33                tarjan(iv);
    34                low[x]=min1(low[x],low[iv]);
    35 
    36            }
    37           else
    38             if(in[iv])
    39               low[x]=min1(low[x],dfn[iv]);
    40      }
    41     if(low[x]==dfn[x])
    42      {
    43       while(stk.top()!=x)
    44       {
    45          in[stk.top()]=false;
    46          stk.pop();
    47 
    48       }
    49      in[stk.top()]=false;
    50         stk.pop();
    51 
    52     }
    53 
    54  }
    55  int main()
    56  {
    57      int i,j,k;
    58     while(cin>>n>>m&&n&&m)
    59     {
    60       while(!stk.empty())stk.pop();
    61       memset(num,0,sizeof(num));
    62       memset(vis,false,sizeof(vis));
    63       memset(side,false,sizeof(side));
    64       memset(in,false,sizeof(in));
    65       ans=0;
    66       for(i=1;i<=n;i++)
    67       {
    68           for(j=1;j<=m;j++)
    69           {
    70             cin>>sd;
    71             if(sd!=i)
    72               {
    73                   ++ans;
    74                   num[i]++;
    75                   side[i][sd]=true;
    76               }
    77           }
    78 
    79       }
    80       deep=1;
    81       for(i=1;i<=n;i++)
    82        {
    83            if(!vis[i]&&num[i]>0)
    84              {
    85               tarjan(i);
    86                ans++;//找到一连通分量加1
    87             }
    88        }
    89     if(ans>0)//多加一次
    90      ans--;
    91     cout<<ans<<endl;
    92     }
    93 
    94     return 0;
    95  }
    View Code
  • 相关阅读:
    UIButton中setTitleEdgeInsets和setImageEdgeInsets的使用
    关于自定义导航条UIBarButtonItem偏移的问题
    iOS端使用二维码扫描(ZBarSDK)和生成(libqrencode)功能
    CocoaPods安装和使用教程
    IOS中NSUserDefaults的用法(轻量级本地数据存储) (转)
    UIPickerView简单选择器的基本使用
    [原]Unity手游之路&lt;三&gt; 基于Unity+Java的聊天室源码
    [原]UML建模语言进阶
    [原]Java多线程编程学习笔记之九:使用wait/notify/notifyAll实现线程间通信的几点说明
    [原]MySQL的表分区
  • 原文地址:https://www.cnblogs.com/sdau--codeants/p/3252740.html
Copyright © 2020-2023  润新知