1124. Mosaic

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

连通分量  Tarjan

大体题意:

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

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

思路:

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

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

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<vector>

#include<map>

#include<cmath>

#include<queue>

#include<stack>

#include<algorithm>



#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];

stack<int>St;

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<<ans<<endl;

    }

    return 0;

}

 

你可能感兴趣的:(OS)