zoukankan      html  css  js  c++  java
  • [bzoj1924] 所驼门王的宝藏

    题意:给你一个网格图,再给你n个点,每个点有一个传送门,可以传送到别的点,传送门有三种,横向,纵向,九宫格,你一开始可以任选一个点为起点,问你最多能经过多少个点。

    题解:

    tarjan+拓扑排序+dag上的dp

    首先这题数据比较水,行和列都是(10^5)级别的

    将能互相到达的点连边,tarjan缩点后变成dag

    考虑在dag上dp,但是要满足拓扑序,所以对缩点后的图进行拓扑排序

    然后直接简单dp即可

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<map>
    #define ll long long
    #define N 100010
    using namespace std;
    
    int n,r,c,e_num,e_num2,top,cnt,tot,ans,dep;
    int vx[N],vy[N],vt[N],nxt[N*50],to[N*50],h[N],nxt2[N*50],to2[N*50],h2[N];
    int dfn[N],low[N],stk[N],bl[N],num[N],inx[N],dp[N];
    int dx[8]={-1,-1,0,1,1,1,0,-1},dy[8]={0,1,1,1,0,-1,-1,-1};
    
    vector<int> v1[N],v2[N];
    map<pair<int,int>,int> mp;
    
    int gi() {
      int x=0,o=1; char ch=getchar();
      while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
      if(ch=='-') o=-1,ch=getchar();
      while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
      return o*x;
    }
    
    void add(int x, int y) {
      nxt[++e_num]=h[x],to[e_num]=y,h[x]=e_num;
    }
    
    void add2(int x, int y) {
      nxt2[++e_num2]=h2[x],to2[e_num2]=y,h2[x]=e_num2;
    }
    
    void tarjan(int u) {
      dfn[u]=low[u]=++dep;
      stk[++top]=u;
      for(int i=h[u]; i; i=nxt[i]) {
        int v=to[i];
        if(!dfn[v]) {
          tarjan(v);
          low[u]=min(low[u],low[v]);
        }
        else if(!bl[v]) low[u]=min(low[u],dfn[v]);
      }
      if(dfn[u]==low[u]) {
        cnt++;
        while(1) {
          int v=stk[top--];
          bl[v]=cnt,num[cnt]++;
          if(u==v) break;
        }
      }
    }
    
    void toposort() {
      for(int i=1; i<=cnt; i++) {
        if(!inx[i]) {
          stk[++top]=i,dfn[++tot]=i;
          dp[i]=num[i];
        }
      }
      while(top) {
        int u=stk[top--];
        for(int i=h2[u]; i; i=nxt2[i]) {
          int v=to2[i];
          inx[v]--;
          if(!inx[v]) stk[++top]=v,dfn[++tot]=v;
        }
      }
    }
    
    int main() {
      n=gi(),r=gi(),c=gi();
      for(int i=1; i<=n; i++) {
        vx[i]=gi(),vy[i]=gi(),vt[i]=gi();
        v1[vx[i]].push_back(i);
        v2[vy[i]].push_back(i);
        mp[make_pair(vx[i],vy[i])]=i;
      }//O(n*logn)
      for(int i=1; i<=n; i++) {
        if(vt[i]==1) {
          int sz=v1[vx[i]].size();
          for(int j=0; j<sz; j++) {
    	if(v1[vx[i]][j]==i) continue;
    	add(i,v1[vx[i]][j]);
          }
        }
        else if(vt[i]==2) {
          int sz=v2[vy[i]].size();
          for(int j=0; j<sz; j++) {
    	if(v2[vy[i]][j]==i) continue;
    	add(i,v2[vy[i]][j]);
          }
        }
        else if(vt[i]==3) {
          for(int j=0; j<8; j++) {
    	pair<int,int> pa=make_pair(vx[i]+dx[j],vy[i]+dy[j]);
    	if(mp[pa]) add(i,mp[pa]);
          }
        }
      }//期望O(n)?
      for(int i=1; i<=n; i++)
        if(!dfn[i]) tarjan(i);
      for(int u=1; u<=n; u++)
        for(int i=h[u]; i; i=nxt[i]) {
          int v=to[i];
          if(bl[u]!=bl[v]) inx[bl[v]]++,add2(bl[u],bl[v]);
        }
      toposort();  
      for(int j=1; j<=cnt; j++) {
        int u=dfn[j];
        for(int i=h2[u]; i; i=nxt2[i]) {
          int v=to2[i];
          dp[v]=max(dp[v],dp[u]+num[v]);
        }
      }
      for(int i=1; i<=cnt; i++)
        ans=max(ans,dp[i]);
      printf("%d
    ", ans);
      return 0;
    }
    
    
  • 相关阅读:
    JAVA中使用FTPClient上传下载
    js 计算题
    js 中的call apply
    js闭包、原型、继承、作用域
    jQuery中.bind() .live() .delegate() .on()的区别
    Javascript中String、Array常用方法介绍
    常用函数
    事件委托,阻止默认事件
    【探讨】javascript事件机制底层实现原理
    css 垂直水平居中
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7636124.html
Copyright © 2011-2022 走看看