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

题目链接:

http://poj.org/problem?id=2375

题目大意:

有一片供奶牛滑雪的滑雪场,可供滑雪的区域是W(宽)*L(长)的矩阵。上边有W*L个点。规定

奶牛从一个点只能向它上、下、左、右相邻的并且高度不大于它的点运动。现在想要在某些

点对之间架设缆车,使得奶牛可以从较低的地方想较高的地方运动,那么问题来了:最少需

要多少辆这样的缆车就可以使奶牛从每个点运动到可供滑雪区域的每个角落。

思路:

把奶牛符合从点u移动到点v的条件当做一条单向边。那么所有点和边就可以构成有向图。根

据奶牛可以从点u移动到邻近并且高度不大于它的点v,可以分为两种情况:(1)点v比点u的高

度低,那么构成一条单向边(u,v);(2)点v和点u的高度相同,那么构成一条双向边(u,v),把

这条双向边拆分成两条单向边(u,v)和(v,u)。然后根据这种关系建图,就构成了一个有向图。

因为双向边可以互相到达,所以邻近的且高度相同的点都可以互相到达,这里可以看做是有向

图的一个强连通分量。根据这样的性质,可将这些点进行缩点处理。

这道题目是求:可以使奶牛从每个点运动到可供滑雪区域的每个角落所需要架设的最小缆车数。

也就是使整个图变成一个强连通有向图。这里就和之前的POJ1236一样了。把一个有向无环图

转换为一个强连通分量。强连通分量的主要特征是:每个点的入度和出度都不为0,那么计算出

入度为0的点的个数SumIn和出度为0的点的个数SumOut,题目就变为了:在入度为0的点和出

出度为0的点之间最少加多少边。很明显的可以看出,答案就是max(SumIn,SumOut)。

AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 550;
const int MAXM = MAXN*MAXN;

struct EdgeNode
{
    int to;
    int next;
}Edges[MAXM << 2];

int Head[MAXM],vis[MAXM],low[MAXM],Map[MAXN][MAXN];
int dfn[MAXM],Stack[MAXM],indegree[MAXM],outdegree[MAXM];
int id,m;

void AddEdges(int u,int v)
{
    Edges[id].to = v;
    Edges[id].next = Head[u];
    Head[u] = id++;
}

int TarBFS(int pos, int lay, int &scc)
{
    vis[pos] = 1;
    dfn[pos] = low[pos] = lay;
    Stack[++m] = pos;
    for(int i = Head[pos]; i != -1; i = Edges[i].next)
    {
        if( !vis[Edges[i].to])
            TarBFS(Edges[i].to, ++lay, scc);
        if(vis[Edges[i].to] == 1)
            low[pos] = min(low[pos], low[Edges[i].to]);
    }

    if(low[pos] == dfn[pos])
    {
        ++scc;
        do
        {
            low[Stack[m]] = scc;
            vis[Stack[m]] = 2;
        }while(Stack[m--] != pos);
    }

    return 0;
}

void Tarjan(int N)
{
    int scc, temp, lay;
    scc = temp = m = 0;
    lay = 1;
    memset(vis,0,sizeof(vis));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    for(int i = 1; i <= N; ++i)
        if(vis[i] == 0)
            TarBFS(i, lay, scc);

    for(int i = 1; i <= N; ++i)
        for(int j = Head[i]; j != -1; j = Edges[j].next)
            if(low[i] != low[Edges[j].to])
            {
                outdegree[low[i]]++;
                indegree[low[Edges[j].to]]++;
            }

    int SumIn,SumOut;
    SumIn = SumOut = 0;

    for(int i = 1; i <= scc; ++i)
    {
        if( !indegree[i] )
            SumIn++;
        if( !outdegree[i] )
            SumOut++;
    }
    if(scc == 1)
        printf("0\n");
    else
        printf("%d\n",max(SumIn,SumOut));
}

int main()
{
    int N,M;
    while(~scanf("%d%d",&M, &N))
    {
        memset(Head,-1,sizeof(Head));
        memset(outdegree,0,sizeof(outdegree));
        memset(indegree,0,sizeof(indegree));
        for(int i = 1; i <= N; ++i)
            for(int j = 1; j <= M; ++j)
                scanf("%d",&Map[i][j]);
        id = 0;
        for(int i = 1; i <= N; ++i)
        {
            for(int j = 1; j <= M; ++j)
            {
                for(int k = -1; k <= 1; ++k)
                {
                    for(int l = -1; l <= 1; ++l)
                    {
                        if(i+k>=1 && i+k<=N && j+l>=1 && j+l<=M && (k==0||l==0) && (k||l))
                        {
                            if(Map[i][j] >= Map[i+k][j+l])
                                AddEdges((i-1)*M+j,(i-1+k)*M+j+l);
                        }
                    }
                }
            }
        }
        Tarjan(M*N);
    }

    return 0;
}
时间: 2024-11-08 18:12:29

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

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 some

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

POJ 2375 Cow Ski Area(强连通)

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

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

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

hdu1269 Tarjan强连通分量 模板(转)

#include<stdio.h> #include<iostream> #include<vector> using namespace std; const int maxn=10010; vector<int>g[maxn]; int Bcnt; int Top; int Index; int low[maxn],dfn[maxn]; int belong[maxn],stack[maxn]; int instack[maxn]; void Init_

tarjan 强连通分量

一.强连通分量定义 有向图强连通分量在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(stronglyconnected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.有向图的极大强连通子图,称为强连通分量(stronglyconnectedcomponents)SCC. 以上是摘自百科的一段对有向图强连通图分量的形式化定义.其实不难理解,举个例子 如上图,{a,b,c,d}为一个强连通分量,{e}

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

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

Tarjan——强连通分量

是的你没有看错,又是Tarjan(说过他发明了很多算法),那么什么是Tarjan 首先看看度娘的解释: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.有向图的极大强连通子图,称为强连通分量(strongly connected components). 是不是没有看懂,我也是 首先了解几个概念: