poj 2375 Cow Ski Area

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

题目大意:FR为自己的牛建立了一个H*W的矩形溜冰场,每一个小方格都有一个高度L,牛只能向相邻的小方格滑动(即上下左右),而且相邻的小方格的高度不能比当前高度高。为了使牛能够从任意一点到达任意其他的点。FR打算买一些ski lifts。它能够连接两个小方格,使得这两个小方格能够相互到达(与高度无关)。问至少需要多少ski lifts。使得牛能够从任意一点到达任意其他的点。

解题思路:将此矩阵看成一个图。如果一个小方格能过到达相邻的一个小方格。那么它们之间就相当于有一条边。然后对此图求强连通分量。ans = Max(入度为0的连通分量数目,出度为0的连通分量数目)。还需要注意的就是如果此图本身就是一个强连通分量,那么答案就是0了,而不是1.(不然会WA)。

ps:如果用g++交的话,tarjan要写成非递归的,不然RE。

View Code
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<bitset>
#include<string>
#include<climits>
#include<cstdio>
#include<vector>
#include<utility>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define IN puts("in")
#define OUT puts("out")
#define FR(x) freopen(x,"r",stdin)
#define FW(x) freopen(x,"w",stdout)
#define MSET(x,y) memset(x,y,sizeof(x))
#define ST system("pause")
using namespace std;

const int maxn = 260000;

struct nd
{
        int u,v,next;
}edge[maxn*4];

int head[maxn],dfn[maxn],low[maxn],vis[maxn],st[maxn],zha[maxn],cur[maxn],belong[maxn],in[maxn],out[maxn],as[505][505];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
int ecnt,cnt,idx,tp,n,m;

void add(int u,int v)
{
        edge[ecnt].u = u;
        edge[ecnt].v = v;
        edge[ecnt].next = head[u];
        head[u] = ecnt++;
}

int judge(int x,int y)
{
        if(x>=0&&y>=0&&x<n&&y<m)return x*m+y+1;
        return 0;
}

void build()
{
        int i,j,k = 1,x;
        ecnt = cnt = idx = tp = 0;
        MSET(head,-1);
        for(i = 0; i < n; ++ i)
                for(j = 0; j < m; ++ j)
                        scanf("%d",&as[i][j]);
        for(i = 0; i < n; ++ i)
                for(j = 0; j < m; ++ j)
                {
                        k = i*m+j+1;
                        for(x = 0; x < 4; ++ x)
                        {
                                int ii = i + dx[x];
                                int jj = j + dy[x];
                                int t = judge(ii,jj);
                                if(t&&as[i][j]>=as[ii][jj]) add(k,t);
                        }
                }
}

void tarjan(int x)
{
        int i,v,top = 0,u;
        zha[++top] = x;
        while(top)
        {
                u = zha[top];
                if(!vis[u]){
                        st[++tp] = u;
                        vis[u] = 1;
                }

                if(!dfn[u]) dfn[u]=low[u]=++idx;
                for(; cur[u]!=-1; cur[u]=edge[cur[u]].next){
                        v = edge[cur[u]].v;
                        if(dfn[v]){
                                if(vis[v]) low[u] = min(low[u],dfn[v]);
                                continue;
                        }
                        zha[++top] = v;
                        break;
                }

                if((cur[u]==-1)&&(dfn[u]==low[u])){
                        ++cnt;
                        do{
                                v = st[tp--];
                                vis[v] = 0;
                                belong[v] = cnt;
                        }while(v!=u);
                }
                if(zha[top]==u){
                        --top;
                        v = zha[top];
                        if(top) low[v] = min(low[v],low[u]);
                }
        }
}

void processing()
{
        int i,j,k,t,u,v;
        while(cin>>m>>n)
        {
                build();
                MSET(vis,0);
                MSET(dfn,0);
                MSET(belong,0);
                MSET(in,0);
                MSET(out,0);
                for(i = 1; i <= n * m; ++ i) cur[i] = head[i];
                for(i = 1; i <= n * m; ++ i)
                        if(!dfn[i])
                                tarjan(i);
                if(cnt==1){puts("0");continue;}
                for(i = 0; i < ecnt; ++ i)
                {
                        u = belong[edge[i].u];
                        v = belong[edge[i].v];
                        if(v!=u){out[u]++; in[v]++;}
                }
                k = 0; t = 0;
                for(i = 1; i <= cnt; ++ i)
                {
                        if(!out[i])k++;
                        if(!in[i]) t++;
                }
                printf("%d\n",max(k,t));
        }
}

int main()
{
        processing();
        return 0;
}

posted on 2012-07-04 09:46  aigoruan  阅读(220)  评论(0)    收藏  举报

导航