POJ 2375 Cow Ski Area[连通分量]

题目链接:http://poj.org/problem?id=2375
题目大意:一片滑雪场,奶牛只能向相邻的并且不高于他当前高度的地方走。想加上缆车是的奶牛能从低的地方走向高的地方,
求最少加的缆车数,是的奶牛可以从任意一个角落到达任意另外的角落
解题思路:奶牛可以向相邻的不高于他的地方走,相当于u,v之前连通。若想加上缆车是图成为连通图,
数目就是max(root, leave);
思路同POJ 1236

代码如下:

#include<stdio.h>

#include<string.h>

#include<iostream>

using namespace std;

#define M 505

#define N 2000005

struct Edge

{

    int v, next;

}edge[N];



int node[N], stack[N], instack[N], dfn[N], out[N], in[N];

int low[N], belong[N], index, cnt_edge, n, m, cnt_tar, top;

int ee[N][2];

int map[M][M];

int dir[4][2]={{1, 0}, {-1, 0}, {0, 1}, {0, -1}};



void add_Edge(int u, int v)

{

    edge[cnt_edge].next=node[u];

    edge[cnt_edge].v=v;

    node[u]=cnt_edge++;

}

void tarjan(int u)

{

    int i, j, v;

    dfn[u]=low[u]=++index;

    stack[++top]=u;

    instack[u]=1;

    for(i=node[u]; i!=-1; i=edge[i].next)

    {

        v=edge[i].v;

        if(!dfn[v])

        {

            tarjan(v);

            low[u]=min(low[u], low[v]);

        }

        else if(instack[v])

            low[u]=min(low[u], dfn[v]);

    }

    if(dfn[u]==low[u])

    {

        cnt_tar++;

        do

        {

            j=stack[top--];

            instack[j]=0;

            belong[j]=cnt_tar;

        }while(j!=u);

    }

}

void solve()

{

    int i;

    top=0, index=0, cnt_tar=0;

    memset(dfn, 0, sizeof(dfn));

    memset(low, 0, sizeof(low));

    for(i=1; i<=n; i++)

        if(!dfn[i])

            tarjan(i);

}

int main()

{

    int i, ii, w, l, j, x, y;

    while(scanf("%d%d", &l, &w)!=EOF)

    {

        cnt_edge=0, m=1, n=l*w;

        memset(node, -1, sizeof(node));

        memset(in, 0, sizeof(in));

        memset(out, 0, sizeof(out));

        for(i=1; i<=w; i++)

        {

            for(j=1; j<=l; j++)

                scanf("%d", &map[i][j]);

        }

        for(i=1; i<=w; i++)

            for(j=1; j<=l; j++)

                for(ii=0; ii<4; ii++)

                {

                    int x=i+dir[ii][0], y=j+dir[ii][1];

                    if(x>=1&&x<=w&&y>=1&&y<=l)

                    {

                        if(map[x][y]<=map[i][j])

                        {

                            add_Edge((i-1)*l+j, (x-1)*l+y);

                            ee[m][0]=(i-1)*l+j, ee[m++][1]=(x-1)*l+y;

                        }

                    }

                }

        solve();

        for(i=1; i<=m; i++)

        {

            int xx=belong[ee[i][0]], yy=belong[ee[i][1]];

            if(xx!=yy)

            {

                in[yy]++;

                out[xx]++;

            }

        }

        int innum=0, outnum=0;

        for(i=1; i<=cnt_tar; i++)

        {

            if(in[i]==0)

                innum++;

            if(out[i]==0)

                outnum++;

        }

        if(cnt_tar==1)

            printf("0\n");

        else

            printf("%d\n", max(innum, outnum));

    }

    return 0;

}
View Code

 

你可能感兴趣的:(poj)