SDOI2010所驼门王的宝藏

Posted shxnb666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SDOI2010所驼门王的宝藏相关的知识,希望对你有一定的参考价值。

题面

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

题解

#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;

 

以上是关于SDOI2010所驼门王的宝藏的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1924: [Sdoi2010]所驼门王的宝藏

洛谷2403 [SDOI2010]所驼门王的宝藏

题解 P2403 [SDOI2010]所驼门王的宝藏

P2403 [SDOI2010]所驼门王的宝藏

[SDOI2010]所驼门王的宝藏 --tarjan缩点+最长路

P2403 [SDOI2010]所驼门王的宝藏