Cow Ski Area POJ 2375

12 篇文章 0 订阅

Description

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.

思路:农夫约翰的表弟,农夫罗恩,住在科罗拉多州的山区,最近教他的奶牛滑雪。不幸的是,他的奶牛有些胆小,不敢在当地滑雪场的人群中滑雪,所以FR决定在他的农场后面建造自己的私人滑雪场。FR的滑雪区域是一个宽度为W,长度为L的矩形“土地广场”(1 <= W <= 500;1 <= L <= 500)。每个陆地的平方是海平面以上高度H的积分(0 <= H <= 9,999)。奶牛可以在任何两个相邻的广场之间水平或垂直滑雪,但不能斜着滑。奶牛可以从一个较高的正方形滑到一个较低的正方形,但不能从另一个方向滑,它们可以在两个相邻的相同高度的正方形之间任意方向滑。FR想建立他的滑雪场,这样他的奶牛可以通过滑雪(如上所述)和滑雪升降机的组合在任何两个广场之间旅行。滑雪缆车可以建在滑雪场的任意两个广场之间,无论高度如何。滑雪缆车是双向的。滑雪缆车可以相互交叉,因为它们可以建在离地面不同的高度,多个滑雪缆车可以在同一个广场开始或结束。由于滑雪缆车造价昂贵,FR想要尽量减少他必须建造的滑雪缆车的数量,让他的奶牛可以在他的滑雪区域的所有广场之间穿行。找出最少的滑雪升降机数目,以确保牛只可以通过滑雪和升降机的组合,从任何广场前往任何其他广场。输入*第1行:两个用空格分隔的整数:W和L *第2行。L+1: L行,每行以W个空格分隔的整数表示每平方土地的高度。输出*第1行:一个整数等于FR需要建立的滑雪升降机的最小数量,以确保他的奶牛可以通过滑雪和滑雪升降机的组合从任何广场到任何其他广场

思路:tarjan缩点,如果强连通分量数量等于1,输出0,否则求缩点后入度为0的点的数量x,出度为0的点的数量y,输出max(x,y);(如果re了建议换用c++交,我g++re了4发,c++一发过)

#include <cstdio>
#include<iostream>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
#define ll long long
const int maxm=1000;
const int maxn=1e6;
stack<int>q;int mp[maxm][maxm];
int cnt,n,m,head[maxn],dfn[maxn],low[maxn],co[maxn],tot,id,out[maxn],in[maxn];
struct Edge
{
    int to,next;
}e[maxn*10];
void add(int u,int v)
{
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void init()
{
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    memset(co,0,sizeof(co));
    memset(head,-1,sizeof(head));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    while(!q.empty()) q.pop();
    cnt=0;id=0,tot=0;
}
void tarjan(int u)
{
    q.push(u);
    dfn[u]=low[u]=++tot;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!co[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        id++;
        while(q.top()!=u)
        {
            int x=q.top();
            q.pop();
            co[x]=id;
        }
        co[u]=id;
        q.pop();
    }
}
int js(int i,int j)
{
    return (i-1)*m+j;
}
int main()
{
    while(scanf("%d %d",&m,&n)!=EOF)
    {
        init();
       for(int i=1;i<=n;i++)
       {
           for(int j=1;j<=m;j++)
           {
               scanf("%d",&mp[i][j]);
           }
       }
       for(int i=1;i<=n;i++)
       {
           for(int j=1;j<=m;j++)
           {
               //printf("js(%d %d)=%d js(%d %d)=%d js(%d %d)=%d js(%d %d)=%d\n",i-1,j,js(i-1,j),i+1,j,js(i+1,j),i,j-1,js(i,j-1),i,j+1,js(i,j+1));
               if(i>1&&mp[i][j]>=mp[i-1][j]) add(js(i,j),js(i-1,j));
               if(i<n&&mp[i][j]>=mp[i+1][j]) add(js(i,j),js(i+1,j));
               if(j>1&&mp[i][j]>=mp[i][j-1]) add(js(i,j),js(i,j-1));
               if(j<m&&mp[i][j]>=mp[i][j+1]) add(js(i,j),js(i,j+1));
           }
       }
       int ed=n*m;
        for(int i=1;i<=ed;i++)
        {
            if(dfn[i]==0)
            {
                tarjan(i);
            }
        }

        if(id==1) printf("0\n");
        else
        {
            for(int i=1;i<=ed;i++)
            {
                for(int j=head[i];j!=-1;j=e[j].next)
                {
                    int v=e[j].to;
                    if(co[i]!=co[v])
                    {
                        //printf("i=%d j=%d u=%d v=%d\n",i,v,co[i],co[v]);
                        out[co[i]]++;
                        in[co[v]]++;
                    }
                }
            }
            int x=0,y=0;
            for(int i=1;i<=id;i++)
            {
                //printf("out[%d]=%d in[%d]=%d\n",i,out[i],i,in[i]);
                if(out[i]==0) x++;
                if(in[i]==0) y++;
            }
            printf("%d\n",max(x,y));
        }
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值