zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Java基础知识总结(绝对经典)
    mybatis注解详解
    div行内样式style常用属性
    php中json_decode()和json_encode()的使用方法
    java调用javascript :js引擎rhino
    DeleteDC() 与 ReleaseDC() 的区别 [转]
    non-manifold Mesh(非流形网格)
    C++静态成员函数小结 [转]
    C++ 类的静态成员详细讲解[转]
    CString 转 char*; wstring 转 string
  • 原文地址:https://www.cnblogs.com/liulangye/p/2735834.html
Copyright © 2011-2022 走看看