• 雪场缆车——染色


    题目描述

    约翰的表哥罗恩生活在科罗拉多州.他近来打算教他的奶牛们滑雪,但是奶牛们非常害羞, 不敢在游人如织的度假胜地滑雪.没办法,他只好自己建滑雪场了. 罗恩的雪场可以划分为$W列L行(1≤W≤500;1≤L≤500),每个方格有一个特定的高度H(O≤日≤9999).$奶牛可以在相临方格间滑雪,而且不能由低到高滑.  为了保证任意方格可以互通,罗恩打算造一些直达缆车.缆车很强大,可以连接任意两个方格,而且是双向的.而且同一个方格也可以造多台缆车. 但是缆车的建造费用贵得吓人,所以他希望造尽量少的缆车.那最少需要造多少台呢? 

    思路

      首先看到这题感觉挺简单的,暴力$flood  fill$,然后直接根据颜色数贪心即可。后来我发现我还是太naive了。

      正解:要使整张图形成一个强联通分量,那么必须满足加边之后没有出度为0的点和入度为0的点,于是我们只需要把每个相同高度的地方先染色,然后暴力从高往低连边,统计入度和出度的个数。最后统计入度为0的颜色数和出度为0的颜色数,比一个max即可。

    下面放上简单易懂的代码。

    code

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<map>
    using namespace std;
    const int N=510;
    int a[N][N];
    int n,m;
    int col[N][N],color;
    map<int,int>vis[N*N];
    
    int dx[5]={0,0,1,-1};
    int dy[5]={1,-1,0,0};
    int in[N*N],out[N*N];
    
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    inline bool chk(int x,int y)
    {
        return (x>=1&&x<=n&&y>=1&&y<=m);
    }
    
    inline void bfs1(int x,int y)
    {
        color++;
        queue<int>q1,q2;
        col[x][y]=color;
        q1.push(x);q2.push(y);
        while(!q1.empty())
        {
            int xx=q1.front(),yy=q2.front();
            for(int i=0;i<4;i++)
            {
                x=xx+dx[i];y=yy+dy[i];
                if(!col[x][y]&&chk(x,y)&&a[xx][yy]==a[x][y])
                {
                    q1.push(x);q2.push(y);
                    col[x][y]=color;
                }
            }
            q1.pop();q2.pop();
        }
    }
    
    int main()
    {
        m=read();n=read();
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        a[i][j]=read();
        
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        if(!col[i][j])bfs1(i,j);
        
        /*cout<<endl;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            cout<<col[i][j]<<" ";cout<<endl;
        }*/
        if(color==1){cout<<"0";return 0;}
        
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            for(int k=0;k<4;k++)
            {
                int x=i+dx[k],y=j+dy[k];
                if(!chk(x,y))continue;
                if(!vis[col[i][j]][col[x][y]]&&a[i][j]>a[x][y])
                {
                    out[col[i][j]]++;
                    in[col[x][y]]++;
                    vis[col[i][j]][col[x][y]]=1;
                    vis[col[x][y]][col[i][j]]=1;
                }
            }
        }            
                    
        int ans1=0,ans2=0;
        for(int i=1;i<=color;i++)
        {
            if(!in[i])ans1++;
            if(!out[i])ans2++;
        }
        
        cout<<max(ans1,ans2);
    }

      

  • 相关阅读:
    ArrayList源代码深入剖析
    java线程基础巩固---wait和sleep的本质区别是什么,深入分析(面试常见问题)
    设计模式相关面试问题-模板方法
    设计模式相关面试问题-适配器
    设计模式相关面试问题-单例
    python-面向对象-10-单例
    python-面向对象-11-异常
    ping
    arp欺骗
    list的方法、操作
  • 原文地址:https://www.cnblogs.com/THRANDUil/p/11638503.html
Copyright © 2020-2023  润新知