zoukankan      html  css  js  c++  java
  • [NOI2016]网格

    嘟嘟嘟


    这题前前后后写了大半个上午……


    首先答案肯定是-1,0,1,2这几种。
    思路就是tarjan判有无割点。因为图太大,所以考虑“离散化”,对于每一个蛐蛐,把他周围55的跳蚤拿来建图。为什么不是33呢,因为如果一个蛐蛐在边界,3*3中的方格就会把一个跳蚤算成割点。


    讲道理这题就没了,但是有特别多的细节。首先得特判各种情况,比如(n = 1)(m = 1),只有两个相邻的块,没有蛐蛐的情况……但最为重要的是,这些特判都完事后,求出来的割点还可能是“假割点”,比如这种情况就会这么建图:

    因此对于每一个割点,要判断周围有没有蛐蛐。


    然后我因为用了map,花了一个多点卡常结果还是有两个点TLE了。中午吃完饭换成哈希表,这两个点只用了300ms……
    所以,真爱生命,远离map!

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<assert.h>
    #include<ctime>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 1e5 + 5;
    const int maxN = 2.5e6 + 5;
    const int maxe = 5e7 + 5;
    const ll BAS = 998244353;
    const ll mod = 2333333;
    In ll read()
    {
      ll ans = 0;
      char ch = getchar(), last = ' ';
      while(!isdigit(ch)) last = ch, ch = getchar();
      while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
      if(last == '-') ans = -ans;
      return ans;
    }
    In void write(ll x)
    {
      if(x < 0) x = -x, putchar('-');
      if(x >= 10) write(x / 10);
      putchar(x % 10 + '0');
    }
    In void MYFILE()
    {
    #ifndef mrclr
      freopen("ha.in", "r", stdin);
      freopen("ha.out", "w", stdout);
    #endif
    }
    
    #define pr pair<int, int>
    #define mp make_pair
    
    ll n, m;
    int c, tot = 0;
    struct Node {int x, y;}p[maxn], t[maxN];
    struct Edge
    {
      int nxt, to;
    }e[maxe];
    int head[maxN], ecnt = -1;
    In void addEdge(const int& x, const int& y)
    {
      //printf("-->%d %d
    ", x, y);
      e[++ecnt] = (Edge){head[x], y};
      head[x] = ecnt;
    }
    
    struct Hash
    {
      int head[mod], hcnt;
      pr to[maxN];
      int nxt[maxN], w[maxN];
      In void A(int x, int y, int id)
      {
        int h = (1LL * x * BAS + y) % mod;
        ++hcnt;
        nxt[hcnt] = head[h], to[hcnt] = mp(x, y), w[hcnt] = id;
        head[h] = hcnt;
      }
      In int Q(int x, int y)
      {
        int h = (1LL * x * BAS + y) % mod;
        for(int i = head[h]; i; i = nxt[i])
          if(mp(x, y) == to[i]) return w[i];
        return 0;
      }
    }H;
    
    In bool check(const int& x, const int& y)
    {
      return x > 0 && x <= n && y > 0 && y <= m && ~H.Q(x, y);
    }
    In bool check_dis(const int& x, const int& y, const int& X, const int& Y)
    {
      return abs(x - X) <= 2 && abs(y - Y) <= 2;
    }
    
    In int N(int x, int y)
    {
      int tp = H.Q(x, y);
      if(!tp)
        {
          H.A(x, y, ++tot); tp = tot;
          t[tot] = (Node){x, y};
        }
      return tp;
    }
    
    int a[5][5];
    const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1}, dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
    In void build(const int& x, const int& y, const int& X, const int& Y)
    {
      int u = a[x - X + 2][y - Y + 2];
      for(int i = 0; i < 4; ++i)
        {
          int nx = x - X + dx[i] + 2, ny = y - Y + dy[i] + 2;
          if(a[nx][ny] == -1 || !check_dis(x + dx[i], y + dy[i], X, Y)) continue;
          addEdge(u, a[nx][ny]);
        }
    }
    
    In void solve(const int& x, const int& y)
    {
      for(int i = -2; i <= 2; ++i)
        for(int j = -2; j <= 2; ++j)
          if((i || j) && check(x + i, y + j)) a[i + 2][j + 2] = N(x + i, y + j);
          else a[i + 2][j + 2] = -1;
      for(int i = -2; i <= 2; ++i)
        for(int j = -2; j <= 2; ++j)
          {
    	if(!i && !j) continue;
    	if(~a[i + 2][j + 2]) build(x + i, y + j, x, y);
          }
    }
    
    bool flg_cut = 0;
    int dfn[maxN], low[maxN], cnt = 0, root;
    int col[maxN], ccol = 0;
    In void dfs(int now, const int& _f, const int& id)
    {
      col[now] = id;
      dfn[now] = low[now] = ++cnt;
      int tp = 0;
      for(int i = head[now], v; ~i; i = e[i].nxt)
        {
          if(!dfn[v = e[i].to])
    	{
    	  ++tp;
    	  dfs(v, now, id);
    	  low[now] = min(low[now], low[v]);
    	  if(low[v] >= dfn[now] && (now != root || tp > 1))
    	    {
    	      for(int j = 0; j < 8 && !flg_cut; ++j)
    		{
    		  int nx = t[now].x + dx[j], ny = t[now].y + dy[j];
    		  if(nx > 0 && nx <= n && ny > 0 && ny <= m && H.Q(nx, ny) == -1) flg_cut = 1;
    		}
    	    }
    	}
          else if(v ^ _f) low[now] = min(low[now], dfn[v]);
        }
    }
    
    In bool judge_0(const int& x, const int& y)
    {
      int Col = 0;
      for(int i = -2; i <= 2; ++i)
        for(int j = -2; j <= 2; ++j)
          {
    	int nx = x + i, ny = y + j;
    	if((!i && !j) || !check(nx, ny)) continue;
    	int tp = col[H.Q(nx, ny)];
    	if(Col && Col ^ tp) return 1;
    	Col = tp;
          }
      return 0;
    }
    
    In void init()
    {
      ecnt = -1;
      tot = cnt = ccol = 0; flg_cut = 0;
      Mem(H.head, 0); H.hcnt = 0;
      for(int i = 1; i <= c * 25; ++i)
      dfn[i] = low[i] = col[i] = 0, head[i] = -1;
    }
    
    int main()
    {
      MYFILE();
      db Beg = clock();
      int T = read();
      while(T--)
        {
          n = read(), m = read(), c = read();
          init();
          for(int i = 1; i <= c; ++i)
    	{
    	  p[i].x = read(), p[i].y = read();
    	  H.A(p[i].x, p[i].y, -1);
    	}
          for(int i = 1; i <= c; ++i) solve(p[i].x, p[i].y);
          if(!c)
    	{
    	  if(n * m < 3) puts("-1");
    	  else puts(n == 1 || m == 1 ? "1" : "2");
    	  continue;
    	}
          if(n * m - c == 2)
    	{
    	  puts(~head[1] ? "-1" : "0");
    	  continue;
    	}
          if(n * m - c < 2) {puts("-1"); continue;}
          for(int i = 1; i <= tot; ++i) if(!dfn[i]) root = i, dfs(i, 0, ++ccol);
          bool flg = 0;
          for(int i = 1; i <= c && !flg; ++i)
    	if(judge_0(p[i].x, p[i].y)) flg = 1;
          if(flg) puts("0");
          else
    	{
    	  if(n == 1 || m == 1) puts("1");
    	  else puts(flg_cut ? "1" : "2");
    	}
        }
      db End = clock();
      //printf("%.4lf
    ", (End - Beg) / CLOCKS_PER_SEC);
      return 0;
    }
    
  • 相关阅读:
    springboot(10)logback日志配置
    springboot(9)springboot整合redis
    springboot(8)springboot整合mybatis
    springboot(7)springboot整合freemarker和thymeleaf
    springboot(6)过滤器 监听器 拦截器
    springboot(5)单元测试及MockMVC类的使用及自定义异常处理
    springboot(4)springboot热部署插件及idea热部署及配置文件注解注入
    springboot(3)使用MultipartFile上传数据文件及项目打成jar包
    springboot(2)内置序列化框架为Jackson及springboot文件目录结构
    git rebase
  • 原文地址:https://www.cnblogs.com/mrclr/p/10889001.html
Copyright © 2011-2022 走看看