zoukankan      html  css  js  c++  java
  • 【SDOI2010】所驼门王的宝藏

    题面

    https://www.luogu.org/problem/P2403

    题解

    我写的是让同一行、同一列的点形成一个环,表示它们互相可达。

    $aysn$写的是对于同一行列建一个新点表示互相可达。

    看了窝还是太弱了,还须多练。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<utility>
    #include<algorithm>
    #include<map>
    #define ri register int
    #define N 100500
    using namespace std;
    const int dx[]={-1,-1,-1,0,0,1,1,1},dy[]={1,0,-1,1,-1,1,0,-1};
    int n,r,c;
    int dfn[N],low[N],tot=0,inq[N],stk[N],top=0;
    int f[N];
    int bel[N],cc=0;
    int x[N],y[N],t[N];
    map<pair<int,int>,int> ot;
    vector<pair<int,int> > e;
    vector<int> about[N];
    int val[N];
    
    int idx[N],cntx=0,idy[N],cnty=0;
    vector<int> to[N];
    
    void add_edge(int x,int y) {
      e.push_back(make_pair(x,y));
      to[x].push_back(y);
    }
    
    bool cmpx(int a,int b) {
      return x[a]<x[b] ||(x[a]==x[b] && y[a]<y[b]);
    }
    bool cmpy(int a,int b) {
      return y[a]<y[b] ||(y[a]==y[b] && x[a]<x[b]);
    }
    
    void linkx() {
      sort(idx+1,idx+cntx+1,cmpx);
      for (ri i=1;i<=cntx;i++) {
        if (x[idx[i]]==x[idx[i+1]]) add_edge(idx[i],idx[i+1]);
        else {
          for (ri j=i;;j--) if (x[idx[j]]==x[idx[i]] && x[idx[j-1]]!=x[idx[i]]) 
          {
            if (i!=j) add_edge(idx[i],idx[j]);
            break;
          }
        }
      }
    }
    
    void linky() {
      sort(idy+1,idy+cnty+1,cmpy);
      for (ri i=1;i<=cnty;i++) {
        if (y[idy[i]]==y[idy[i+1]]) add_edge(idy[i],idy[i+1]);
        else {
          for (ri j=i;;j--) if (y[idy[j]]==y[idy[i]] && y[idy[j-1]]!=y[idy[i]]) 
          {
            if (i!=j) add_edge(idy[i],idy[j]);
            break;
          }
        }
      }
    }
    
    int prex(int i){
      if (x[idx[i-1]]==x[idx[i]]) return i-1;
      for (ri j=i;;j++) if (x[idx[j]]==x[idx[i]]&&x[idx[j+1]]!=x[idx[i]]) return j;
    }
    
    void linkx2() {
      sort(idx+1,idx+cntx+1,cmpx);
      for (ri i=1;i<=cntx;i++) if (t[idx[i]]==1) {
        ri j=prex(i);
        while (t[idx[j]]!=1) {
          add_edge(idx[i],idx[j]);
          j=prex(j);
        }
      }
    }
    
    
    int prey(int i){
      if (y[idy[i-1]]==y[idy[i]]) return i-1;
      for (ri j=i;;j++) if (y[idy[j]]==y[idy[i]]&&y[idy[j+1]]!=y[idy[i]]) return j;
    }
    
    void linky2() {
      sort(idy+1,idy+cnty+1,cmpy);
      for (ri i=1;i<=cnty;i++) if (t[idy[i]]==2) {
        ri j=prey(i);
        while (t[idy[j]]!=2) {
          add_edge(idy[i],idy[j]);
          j=prey(j);
        }
      }
    }
    
    void tarjan(int x) {
      dfn[x]=low[x]=++tot; inq[x]=1; stk[++top]=x;
      for (ri i=0,l=to[x].size();i<l;i++) {
        int y=to[x][i];
        if (dfn[y] && !inq[y]) continue;
        if (!dfn[y]) {
          tarjan(y);
          low[x]=min(low[x],low[y]);
        }
        else {
          low[x]=min(low[x],dfn[y]);
        }
      }
      if (low[x]==dfn[x]) {
        ++cc;
        int t;
        do {
          t=stk[top];
          inq[t]=0;
          bel[t]=cc;
          top--;
        }
        while (t!=x);
      }
    }
    
    void makegraph() {
      for (ri i=1;i<=n;i++) val[bel[i]]++;
      int l=e.size();
      for (ri i=0;i<l;i++) 
        if (bel[e[i].first]!=bel[e[i].second]) about[bel[e[i].first]].push_back(bel[e[i].second]);
    }
    
    void dp(int x) {
      if (f[x]!=-1) return;
      f[x]=0;
      for (ri i=0,l=about[x].size();i<l;i++) {
        int y=about[x][i];
        dp(y);
        if (f[y]>f[x]) f[x]=f[y];
      }
      f[x]+=val[x];
    }
    
    int main(){
      scanf("%d %d %d",&n,&r,&c);
      
      for (ri i=1;i<=n;i++) {
        scanf("%d %d %d",&x[i],&y[i],&t[i]);
        ot[make_pair(x[i],y[i])]=i;
      }
      
      for (ri i=1;i<=n;i++) {
        if (t[i]==1) {
          idx[++cntx]=i;
        }
        else if (t[i]==2) {
          idy[++cnty]=i;
        }
        else if (t[i]==3) {
          for (ri j=0;j<8;j++) {
            int nx=x[i]+dx[j],ny=y[i]+dy[j];
            if (ot.count(make_pair(nx,ny))) add_edge(i,ot[make_pair(nx,ny)]);
          }
        }
      }
      
      linkx();
      linky();
      
      for (ri i=1;i<=n;i++) {
        if (t[i]==1 || t[i]==3) {
          idy[++cnty]=i;
        }
        if (t[i]==2 || t[i]==3) {
          idx[++cntx]=i;
        }
      }
      linkx2();
      linky2();
      for (ri i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
      makegraph();
      memset(f,-1,sizeof(f));
      int ans=0;
      for (ri i=1;i<=cc;i++) {
        dp(i);
        if (f[i]>ans) ans=f[i];
      }
      cout<<ans<<endl;
    }
  • 相关阅读:
    第二阶段个人总结7
    第二阶段个人总结6
    第十七周进度报告
    个人总结
    十六周进度报告
    人月神话阅读笔记3
    十五周进度报告
    十四周进度报告
    人月神话阅读笔记2
    购买图书
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11277926.html
Copyright © 2011-2022 走看看