POJ2375 Cow Ski Area 【强连通分量】+【DFS】


Cow Ski Area

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 2323   Accepted: 660

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.

Source

USACO 2004 December Gold

题意:本题描述了一片滑雪场,并且规定奶牛从一个点只能向它相邻的并且高度不大于它的点运动,现在想要在某些点对之间加上缆车使得奶牛也可以从较低点到达较高点,问最少需要多少辆这样的缆车就可以使得奶牛可以从任意一个点运动到滑雪场的每个角落。

题解:对于相邻的高度相同的点,实际上路线是双向的,所以它们构成了强连通,然后这道题可以找出所有强连通,于是就构成了一个DAG,然后答案就是max(入度为0的点,出度为0的点),特别的,当整幅图已经是强连通时答案为0.这题求强连通可以用DFS,省去不少麻烦。

#include <stdio.h>
#include <string.h>
#define maxn 502

int map[maxn][maxn], scc[maxn][maxn];
int sccNum, id, head[maxn * maxn], n, m;
bool in[maxn * maxn], out[maxn * maxn];
struct Node{
    int to, next;
} E[maxn * maxn << 2];

void addEdge(int u, int v)
{
    E[id].to = v;
    E[id].next = head[u];
    head[u] = id++;
}

void getMap(int n, int m)
{
    int i, j; id = 0;
    for(i = 1; i <= n; ++i)
        for(j = 1; j <= m; ++j)
            scanf("%d", &map[i][j]);
}

void DFS(int x, int y)
{
    if(scc[x][y]) return;
    scc[x][y] = sccNum;
    if(x + 1 <= n && map[x+1][y] == map[x][y]) DFS(x + 1, y);
    if(x - 1 >= 0 && map[x-1][y] == map[x][y]) DFS(x - 1, y);
    if(y + 1 <= m && map[x][y+1] == map[x][y]) DFS(x, y + 1);
    if(y - 1 >= 0 && map[x][y-1] == map[x][y]) DFS(x, y - 1);
}

void solve(int n, int m)
{
    memset(scc, 0, sizeof(scc));
    memset(in, 0, sizeof(in));
    memset(out, 0, sizeof(out));
    memset(head, -1, sizeof(head));
    sccNum = 0;
    int i, j, ans1 = 0, ans2 = 0;
    for(i = 1; i <= n; ++i)
        for(j = 1; j <= m; ++j)
            if(!scc[i][j]){
                ++sccNum; DFS(i, j);
            }
    for(i = 1; i <= n; ++i)
        for(j = 1; j <= m; ++j){
            if(i + 1 <= n && scc[i][j] != scc[i+1][j]){
                if(map[i][j] > map[i+1][j]){
                    addEdge(scc[i][j], scc[i+1][j]);
                    in[scc[i+1][j]] = out[scc[i][j]] = 1;
                } else{
                    addEdge(scc[i+1][j], scc[i][j]);
                    in[scc[i][j]] = out[scc[i+1][j]] = 1;
                }
            }
            if(j + 1 <= m && scc[i][j] != scc[i][j+1]){
                if(map[i][j] > map[i][j+1]){
                    addEdge(scc[i][j], scc[i][j+1]);
                    in[scc[i][j+1]] = out[scc[i][j]] = 1;
                } else{
                    addEdge(scc[i][j+1], scc[i][j]);
                    in[scc[i][j]] = out[scc[i][j+1]] = 1;
                }
            }
        }
    if(sccNum != 1)
        for(i = 1; i <= sccNum; ++i){
            if(!in[i]) ++ans1;
            if(!out[i]) ++ans2;
        }
    if(ans1 < ans2) ans1 = ans2;
    printf("%d\n", ans1);
}

int main()
{
    while(scanf("%d%d", &m, &n) == 2){
        getMap(n, m);
        solve(n, m);
    }
    return 0;
}
时间: 2025-01-16 17:31:31

POJ2375 Cow Ski Area 【强连通分量】+【DFS】的相关文章

POJ 2375 Cow Ski Area (强连通分量)

题目地址:POJ 2375 对每一个点向与之相邻并h小于该点的点加有向边. 然后强连通缩点.问题就转化成了最少加几条边使得图为强连通图,取入度为0和出度为0的点数的较大者就可以.注意,当强连通分量仅仅有一个的时候.答案是0,而不是1. 代码例如以下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #in

POJ2375 Cow Ski Area (强连通)(缩点)

Cow Ski Area Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3323   Accepted: 919 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 some

POJ2375 Cow Ski Area (添最少边构造强连通分量的某个与入度出度相关的结论)

题意:本题描述了一片滑雪场,并且规定奶牛从一个点只能向它相邻的并且高度不大于它的点运动,现在想要在某些点对之间加上缆车使得奶牛也可以从较低点到达较高点,问最少需要多少辆这样的缆车就可以使得奶牛可以从任意一个点运动到滑雪场的每个角落. 思路:即问至少加多少条边使图变成强联通图,先缩点成DAG. 不难知道强连通分量的所有节点的入度和出度均不为0,可以统计DAG上的入度和出度为0的个数分别是a,b.然后答案即为max(a,b). 只是发现入度为0和出度为0的点可以按某种方式相连接总能构造出一个强连通分

POJ2375 Cow Ski Area【Tarjan】【强连通分量】

题目链接: http://poj.org/problem?id=2375 题目大意: 有一片供奶牛滑雪的滑雪场,可供滑雪的区域是W(宽)*L(长)的矩阵.上边有W*L个点.规定 奶牛从一个点只能向它上.下.左.右相邻的并且高度不大于它的点运动.现在想要在某些 点对之间架设缆车,使得奶牛可以从较低的地方想较高的地方运动,那么问题来了:最少需 要多少辆这样的缆车就可以使奶牛从每个点运动到可供滑雪区域的每个角落. 思路: 把奶牛符合从点u移动到点v的条件当做一条单向边.那么所有点和边就可以构成有向图.

POJ 2375 Cow Ski Area(强连通)

POJ 2375 Cow Ski Area 题目链接 题意:给定一个滑雪场,每个点能向周围4个点高度小于等于这个点的点滑,现在要建电缆,使得任意两点都有路径互相可达,问最少需要几条电缆 思路:强连通缩点,每个点就是一个点,能走的建边,缩点后找入度出度为0的个数的最大值就是答案,注意一开始就强连通了答案应该是0 代码: #include <cstdio> #include <cstring> #include <stack> #include <algorithm&

D - Cow Ski Area

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

【连通图|强连通分量+dfs】POJ-3160 Father Christmas flymouse

Father Christmas flymouse Time Limit: 1000MS Memory Limit: 131072K Description After retirement as contestant from WHU ACM Team, flymouse volunteered to do the odds and ends such as cleaning out the computer lab for training as extension of his contr

POJ 2375 Cow Ski Area【tarjan】

题目大意:一个W*L的山,每个山有个高度,当且仅当一个山不比它相邻(有公共边的格子)的山矮时能够滑过去,现在可以装化学电梯来无视山的高度滑雪,问最少装多少电梯使得任意两点都可到达 思路:最后一句话已经把强连通模型裸裸地说出来了 那问题变成了一个图最小加几条边变成强连通图的经典问题,比较一下出度为0和入度为0的点的个数的大小即可,还有个特例只有一个SCC的情况 #include<cstdio> #include<string.h> #include<iostream> #

POJ-3180 The Cow Prom(tarjan求强连通分量)

题目链接:http://poj.org/problem?id=3180 题目大意:求一个有向图的强连通分量 算法:求强连通分量首选tarjan算法 这里简单说一下tarjan的思路 时间戳是什么:在搜索时访问的最早时间 维护dfn[u]表示u的时间戳 low[u]表示u点所能回到的最早的祖先的时间戳 开一个栈,把搜索的点入栈.搜索时遇到已经搜过的点,取low[u]和dfn[v]的最小值,回溯时取low[u]和low[v]的最小值(标记上传)传到dfn[u]<=low[u]时表示已经回溯到最上面的