zoukankan      html  css  js  c++  java
  • POJ2375 Cow Ski Area 加最少的边构成强连通图

    /*
    *State: POJ2375 26396K    938MS    C++    2743B 险过:limit:1000ms
    *题目大意:
    *        FR为自己的牛建立了一个H*W的矩形溜冰场,每一个小方格都
    *        有一个高度L,牛只能向相邻的小方格滑动(即上下左右),
    *        而且相邻的小方格的高度不能比当前高度高。为了使牛能够从
    *        任意一点到达任意其他的点。FR打算买一些ski lifts。它能够
    *        连接两个小方格,使得这两个小方格能够相互到达(与高度无
    *        关)。问至少需要多少ski lifts。使得牛能够从任意一点到达
    *        任意其他的点。
    *解题思路:
    *        第一步,构图,之后用tarjan算法缩点,然后再根据入度为0
    *        和出度为0的强连通分量的数量的最大值为构强连通的最少边求出。
    *解题感想:
    *        一开始用了vector,直接TLE,估计是vector清空那一块太费时间。
    *        ps:求缩点的出入度那一步比较妙,巧用了标识法,挺常用的,要
    *        记住。
    */
    View Code
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int MAX = 505;
    const int MAXN = 250005;
    
    typedef struct _node
    {
        int v, next;
    }N;
    N edge[MAXN * 4];
    int farm[MAX][MAX];
    int dir[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
    int dfn[MAXN], low[MAXN], step;
    int inS[MAXN], id[MAXN], scc, myS[MAXN], top;
    int in[MAXN], out[MAXN], cntEdge, head[MAXN];
    
    void init()
    {
        cntEdge = step = scc = top = 0;
        for(int i = 0; i < MAXN; i++)
        {
            head[i] = -1;
            dfn[i] = low[i] = -1;
            id[i] = -1;
            in[i] = out[i] = 0;
            inS[i] = 0;
        }
    }
    
    void tarjan(int n)
    {
        dfn[n] = low[n] = ++step;
        myS[top++] = n;
        inS[n] = 1;
        for(int f = head[n]; f != -1; f = edge[f].next)
        {
            int son = edge[f].v;
            if(dfn[son] == -1)
            {
                tarjan(son);
                low[n] = min(low[n], low[son]);
            }
            else if(inS[son] != 0)
                low[n] = min(low[n], dfn[son]);
        }
    
        if(low[n] == dfn[n])
        {
            int tmp;
            do
            {
                tmp = myS[--top];
                inS[tmp] = 0;
                id[tmp] = scc;
            }while(myS[top] != n);
            scc++;
        }
    }
    
    void addEdge(int u, int v)
    {
        edge[cntEdge].v = v;
        edge[cntEdge].next = head[u];
        head[u] = cntEdge++;
    }
    
    void bulid(int w, int l)
    {
        int u, v;
        for(int i = 0; i < l; i++)
            for(int j = 0; j < w; j++)
            {
                for(int k = 0; k < 4; k++)
                {
                    int ni, nj; 
                    ni = i + dir[k][0];
                    nj = j + dir[k][1];
                    if(ni >= 0 && ni < l && nj >= 0 && nj < w)
                    {
                        if(farm[i][j] >= farm[ni][nj])
                        {
                            u = i * w + j;
                            v = ni * w + nj;
                            addEdge(u, v);
                        }
                    }
                }
            }
    }
    
    int main(void)
    {
    #ifndef ONLINE_JUDGE 
        freopen("in.txt", "r", stdin);
    #endif
    
        int w, l;
        while(scanf("%d %d", &w, &l) == 2)
        {
            init();
            for(int i = 0; i < l; i++)
                for(int j = 0; j < w; j++)
                    scanf("%d", &farm[i][j]);
            bulid(w, l);
            int n = w * l;
    
            for(int i = 0; i < n; i++)
            {
                if(dfn[i] == -1)
                    tarjan(i);
            }
            int u, v;
            for(int i = 0; i < n; i++)
            {
                for(int j = head[i]; j != -1; j = edge[j].next)
                {
                    u = i, v = edge[j].v;
                    if(id[u] == id[v])
                        continue;
                    else
                    {
                        in[id[v]]++;
                        out[id[u]]++;
                    }
                }    
            }
            int inNum = 0, outNum = 0;
            for(int i = 0; i < scc; i++)
            {
                if(!in[i])
                    inNum++;
                if(!out[i])
                    outNum++;
            }
            if(scc >= 2)
                printf("%d\n", max(inNum, outNum));
            else
                printf("0\n");
        }
        return 0;
    }
  • 相关阅读:
    Linnia学习记录
    漫漫考研路
    ENS的学习记录
    KnockoutJS 3.X API 第四章 数据绑定(4) 控制流with绑定
    KnockoutJS 3.X API 第四章 数据绑定(3) 控制流if绑定和ifnot绑定
    KnockoutJS 3.X API 第四章 数据绑定(2) 控制流foreach绑定
    KnockoutJS 3.X API 第四章 数据绑定(1) 文本及样式绑定
    KnockoutJS 3.X API 第三章 计算监控属性(5) 参考手册
    KnockoutJS 3.X API 第三章 计算监控属性(4)Pure computed observables
    KnockoutJS 3.X API 第三章 计算监控属性(3) KO如何实现依赖追踪
  • 原文地址:https://www.cnblogs.com/cchun/p/2645070.html
Copyright © 2011-2022 走看看