OpenJ_Bailian - 2375 Cow Ski Area

题目连接:http://bailian.openjudge.cn/practice/2375?lang=en_US

题面

Farmer John’s cousin, Farmer Ron, who lives in the mountains of Colorado, has recently taught his cows to ski. Unfortunately, his cows are somewhat timid and are afraid to ski among crowds of people at the local resorts, so FR has decided to construct his own private ski area behind his farm.

FR’s ski area is a rectangle of width W and length L of ‘land squares’ (1 <= W <= 500; 1 <= L <= 500). Each land square is an integral height H above sea level (0 <= H <= 9,999). Cows can ski horizontally and vertically between any two adjacent land squares, but never diagonally. Cows can ski from a higher square to a lower square but not the other way and they can ski either direction between two adjacent squares of the same height.

FR wants to build his ski area so that his cows can travel between any two squares by a combination of skiing (as described above) and ski lifts. A ski lift can be built between any two squares of the ski area, regardless of height. Ski lifts are bidirectional. Ski lifts can cross over each other since they can be built at varying heights above the ground, and multiple ski lifts can begin or end at the same square. Since ski lifts are expensive to build, FR wants to minimize the number of ski lifts he has to build to allow his cows to travel between all squares of his ski area.

Find the minimum number of ski lifts required to ensure the cows can travel from any square to any other square via a combination of skiing and lifts.
Input
* Line 1: Two space-separated integers: W and L

  • Lines 2..L+1: L lines, each with W space-separated integers corresponding to the height of each square of land.
    Output
  • Line 1: A single integer equal to the minimal number of ski lifts FR needs to build to ensure that his cows can travel from any square to any other square via a combination of skiing and ski lifts
    Sample Input
    9 3
    1 1 1 2 2 2 1 1 1
    1 2 1 2 3 2 1 2 1
    1 1 1 2 2 2 1 1 1
    Sample Output
    3
    Hint
    This problem has huge input data,use scanf() instead of cin to read data to avoid time limit exceed.

OUTPUT DETAILS:

FR builds the three lifts. Using (1, 1) as the lower-left corner,
the lifts are (3, 1) <-> (8, 2), (7, 3) <-> (5, 2), and (1, 3) <->
(2, 2). All locations are now connected. For example, a cow wishing
to travel from (9, 1) to (2, 2) would ski (9, 1) -> (8, 1) -> (7,
1) -> (7, 2) -> (7, 3), take the lift from (7, 3) -> (5, 2), ski
(5, 2) -> (4, 2) -> (3, 2) -> (3, 3) -> (2, 3) -> (1, 3), and then
take the lift from (1, 3) - > (2, 2). There is no solution using
fewer than three lifts.
题意:有一块面积为w*l的雪地,每一单位面积都有固定的高度,奶牛可以从高处滑到低处,或者在相同高度滑雪,只能上下左右移动,不能斜着移动,然而奶牛可以借助块与块之间的升降机向高处滑动,并且升降机是双向的,而且可以建在不相邻的块之间,问最少要建立多少升降机才能使得奶牛能够从任意的块到达任意的块。

分析及思路:

经典的强连通问题,先对每个强连通进行缩点,然后对于每个缩点之后的点求入度和出度,统计入度为零的点的数量t1及出度为零的点的数量t2即可,最后输出t1和t2的最大值。建图时每个点向上下左右搜即可。
有一个巨坑就是poj会因为堆栈太多而RE,貌似需要手动扩栈,但本蒟蒻的手动扩栈在pojCE了。最后只好换个oj交题。
AC代码:

#include<iostream>
#include<cstring>
#include<stack>
#define rep(i,x,n) for(int i=x;i<n;i++)
#define per(i,x,n) for(int i=n-1;i>=x;i--)
using namespace std;
//head
int const maxn=3e5;
int w,l,cnt,cur=0,tot=0,head[maxn],color[maxn],in[maxn],out[maxn],low[maxn],dfn[maxn],vis[maxn];
int mp[506][506];
struct Edge{int to,next;}edge[6*maxn];
void addedge(int x,int y){edge[cur].to=y;edge[cur].next=head[x];head[x]=cur++;}
int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
void build()
{
    rep(i,0,l)
    rep(j,0,w)
    {
        int x=i*w+j;
        if(i!=0&&mp[i][j]>=mp[i-1][j]){int y=x-w;addedge(x,y);}
        if(j!=0&&mp[i][j]>=mp[i][j-1]){int y=x-1;addedge(x,y);}
        if(i!=l-1&&mp[i][j]>=mp[i+1][j]){int y=x+w;addedge(x,y);}
        if(j!=w-1&&mp[i][j]>=mp[i][j+1]){int y=x+1;addedge(x,y);}
    }
}
stack<int>q;
void tarjan(int x)
{
    low[x]=dfn[x]=++tot;
    vis[x]=1;
    q.push(x);
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        int nx=edge[i].to;
        if(!dfn[nx])
        {
            tarjan(nx);
            low[x]=min(low[x],low[nx]);
        }
        else if(vis[nx])
            low[x]=min(low[x],dfn[nx]);
    }
    if(low[x]==dfn[x])
    {
        cnt=0;int tmp=0;
        while(!q.empty())
        {
            tmp=q.top();
            q.pop();
            vis[tmp]=0;
            color[tmp]=cur;
            if(tmp==x)break;
        }
        cur++;
    }
}
int main()
{
     ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     memset(head,-1,sizeof(head));
     cin>>w>>l;
     rep(i,0,l)
     rep(j,0,w)
     cin>>mp[i][j];
     build();
     int len=w*l;
     cur=0;
     rep(i,0,len)if(!dfn[i])tarjan(i);
     if(cur==1){cout<<0<<endl;return 0;}
     rep(i,0,len)
     {
         for(int x=head[i];x!=-1;x=edge[x].next)
         if(color[i]!=color[edge[x].to]){out[color[i]]++;in[color[edge[x].to]]++;}
     }
     int t1=0,t2=0;
     rep(i,0,cur)
     {
         if(in[i]==0)t1++;
         if(out[i]==0)t2++;
     }
     cout<<max(t1,t2)<<endl;
     return 0;
}

版权声明:本文为原创文章,转载请标明出处。
https://blog.csdn.net/u014390156

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值