1124. Mosaic

http://acm.timus.ru/problem.aspx?space=1&num=1124

连通分量  Tarjan

大体题意:

n个箱子 每个里面有m个物品 但对应编号有可能错误 要求把所以物品归位  求最少move

一次move 有两种情况 1,把一个物品从一个箱子里拿到里一个箱子了(回来,不会来都可以)  2,空手从一个箱子到另一个箱子

思路:

首先每个放错的物品都得被移动一次    然后就是从一个连通分量移动到另一个连通分量(空手移动)

注意移动到第一个连通分量无需花费时间 而已要注意为0的情况

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define LL long long
//#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;
const int INF=0x3f3f3f3f;
const int N=505;
bool side[N][N];
int low[N],dfn[N],deep;
bool in[N],visited[N];
int difnum[N];
stackSt;
int n,m;
void Tarjan(int x)
{
    low[x]=dfn[x]=deep++;
    visited[x]=true;
    St.push(x);
    in[x]=true;
    for(int l=1;l<=n;++l)
    {
        if(side[x][l]==false)
        continue;
        if(!visited[l])
        {
            Tarjan(l);
            low[x]=min(low[x],low[l]);
        }else if(in[l])
        {
            low[x]=min(low[x],dfn[l]);
        }
    }
    if(low[x]==dfn[x])
    {
        while(St.top()!=x)
        {
            in[St.top()]=false;
            St.pop();
        }
        in[St.top()]=false;
        St.pop();
    }
}
int main()
{
    //freopen("data.txt","r",stdin);
    while(cin>>n>>m)
    {
        memset(side,false,sizeof(side));
        memset(difnum,0,sizeof(difnum));
        int ans=0;
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=m;++j)
            {
                int l;
                cin>>l;
                if(l!=i)
                {
                    ++ans;
                    side[i][l]=true;
                    ++difnum[i];
                }
            }
        }
        memset(visited,false,sizeof(visited));
        deep=0;
        for(int i=1;i<=n;++i)
        {
            if(!visited[i]&&difnum[i]>0)
            {
                Tarjan(i);
                ++ans;
            }
        }
        if(ans>0)
        --ans;
        cout<

 

转载于:https://www.cnblogs.com/liulangye/archive/2012/10/23/2735834.html

你可能感兴趣的:(1124. Mosaic)