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
      1 //第三次优化,试试时间还能否优化,由于题目特殊,只有一组数据。
      2 //State: POJ2375 266MS    C++    2298B
      3 //自己写的栈,居然快了那么多,汗~
      4 #include <iostream>
      5 #include <cstdio>
      6 #include <cstring>
      7 using namespace std;
      8 
      9 const int MAX = 505;
     10 const int MAXN = 250005;
     11 
     12 typedef struct _node
     13 {
     14     int v, next;
     15 }N;
     16 N edge[MAXN * 4];
     17 int farm[MAX][MAX];
     18 int dir[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
     19 int dfn[MAXN], low[MAXN], step;
     20 int inS[MAXN], id[MAXN], scc, myS[MAXN], top;
     21 int in[MAXN], out[MAXN], cntEdge, head[MAXN];
     22 
     23 void init()
     24 {
     25     cntEdge = step = scc = top = 0;
     26     for(int i = 0; i < MAXN; i++)
     27     {
     28         head[i] = -1;
     29         dfn[i] = low[i] = -1;
     30         id[i] = -1;
     31         in[i] = out[i] = 0;
     32         inS[i] = 0;
     33     }
     34 }
     35 
     36 void tarjan(int n)
     37 {
     38     dfn[n] = low[n] = ++step;
     39     myS[top++] = n;
     40     inS[n] = 1;
     41     for(int f = head[n]; f != -1; f = edge[f].next)
     42     {
     43         int son = edge[f].v;
     44         if(dfn[son] == -1)
     45         {
     46             tarjan(son);
     47             low[n] = min(low[n], low[son]);
     48         }
     49         else if(inS[son] != 0)
     50             low[n] = min(low[n], dfn[son]);
     51     }
     52 
     53     if(low[n] == dfn[n])
     54     {
     55         int tmp;
     56         do
     57         {
     58             tmp = myS[--top];
     59             inS[tmp] = 0;
     60             id[tmp] = scc;
     61         }while(myS[top] != n);
     62         scc++;
     63     }
     64 }
     65 
     66 void addEdge(int u, int v)
     67 {
     68     edge[cntEdge].v = v;
     69     edge[cntEdge].next = head[u];
     70     head[u] = cntEdge++;
     71 }
     72 
     73 void bulid(int w, int l)
     74 {
     75     int u, v;
     76     for(int i = 0; i < l; i++)
     77         for(int j = 0; j < w; j++)
     78         {
     79             for(int k = 0; k < 4; k++)
     80             {
     81                 int ni, nj; 
     82                 ni = i + dir[k][0];
     83                 nj = j + dir[k][1];
     84                 if(ni >= 0 && ni < l && nj >= 0 && nj < w)
     85                 {
     86                     if(farm[i][j] >= farm[ni][nj])
     87                     {
     88                         u = i * w + j;
     89                         v = ni * w + nj;
     90                         addEdge(u, v);
     91                     }
     92                 }
     93             }
     94         }
     95 }
     96 
     97 int main(void)
     98 {
     99 #ifndef ONLINE_JUDGE 
    100     freopen("in.txt", "r", stdin);
    101 #endif
    102 
    103     int w, l;
    104     while(scanf("%d %d", &w, &l) == 2)
    105     {
    106         init();
    107         for(int i = 0; i < l; i++)
    108             for(int j = 0; j < w; j++)
    109                 scanf("%d", &farm[i][j]);
    110         bulid(w, l);
    111         int n = w * l;
    112 
    113         for(int i = 0; i < n; i++)
    114         {
    115             if(dfn[i] == -1)
    116                 tarjan(i);
    117         }
    118         int u, v;
    119         for(int i = 0; i < n; i++)
    120         {
    121             for(int j = head[i]; j != -1; j = edge[j].next)
    122             {
    123                 u = i, v = edge[j].v;
    124                 if(id[u] == id[v])
    125                     continue;
    126                 else
    127                 {
    128                     in[id[v]]++;
    129                     out[id[u]]++;
    130                 }
    131             }    
    132         }
    133         int inNum = 0, outNum = 0;
    134         for(int i = 0; i < scc; i++)
    135         {
    136             if(!in[i])
    137                 inNum++;
    138             if(!out[i])
    139                 outNum++;
    140         }
    141         if(scc >= 2)
    142             printf("%d\n", max(inNum, outNum));
    143         else
    144             printf("0\n");
    145     }
    146     return 0;
    147 }
  • 相关阅读:
    顺序栈的基本操作(C语言)
    简单加密-维吉尼亚
    单链表的反转
    单链表的排序
    SVN信息泄露漏洞
    SQLi-labs Page-2_Less-21---Less-28a
    dedecms 任意密码重置 验证凭证回传
    ThinkCMF缓存Getshell
    ThinkCMF X2.2.0多处SQL注入漏洞
    SQLi-LABS Page-4(Challenges)
  • 原文地址:https://www.cnblogs.com/cchun/p/2641116.html
Copyright © 2011-2022 走看看