1. 程式人生 > >洛咕 P2403 [SDOI2010]所駝門王的寶藏

洛咕 P2403 [SDOI2010]所駝門王的寶藏

簡單tarjan。

一行的橫天門如果暴力連邊會被卡成平方,所以只要相鄰兩個橫天門連雙向邊,再隨便選一個橫天門向整行連邊即可。縱寰門同理。ziyou門直接map暴力連邊。

然後tarjan直接dp。

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
std::map<std::pair<int,int>,int>M;
struct yyb{int x,y,o,i;}s[100010];
int fir[100010],dis[1000010],nxt[1000010],id;
il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
il bool cmp1(const yyb&a,const yyb&b){
    if(a.x!=b.x)return a.x<b.x;
    else return a.o==1;
}
il bool cmp2(const yyb&a,const yyb&b){
    if(a.y!=b.y)return a.y<b.y;
    else return a.o==2;
}
const int dX[]={1,1,1,0,0,-1,-1,-1},dY[]={1,0,-1,1,-1,1,0,-1};
int dfn[100010],low[100010],stk[100010],top,ins[100010],scc[100010],w[100010];
std::vector<int>S[100010];
il vd tarjan(int x){
    dfn[x]=low[x]=++dfn[0];stk[++top]=x;ins[x]=1;
    for(int i=fir[x];i;i=nxt[i])
        if(!dfn[dis[i]])tarjan(dis[i]),low[x]=std::min(low[x],low[dis[i]]);
        else if(ins[dis[i]])low[x]=std::min(low[x],dfn[dis[i]]);
    if(dfn[x]==low[x]){
        ++scc[0];
        while(stk[top+1]!=x)ins[stk[top]]=0,scc[stk[top]]=scc[0],S[scc[0]].push_back(stk[top]),--top;
    }
}
int f[100010];
il int dp(int x){
    if(f[x])return f[x];
    for(int i=0;i<S[x].size();++i)
        for(int j=fir[S[x][i]];j;j=nxt[j])
            if(scc[dis[j]]!=x)
                f[x]=std::max(f[x],dp(scc[dis[j]]));
    return f[x]=f[x]+S[x].size();
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("2403.in","r",stdin);
    freopen("2403.out","w",stdout);
#endif
    int n=gi(),r=gi(),c=gi();
    for(int i=1;i<=n;++i)s[i].x=gi(),s[i].y=gi(),s[i].o=gi(),s[i].i=i,M[std::make_pair(s[i].x,s[i].y)]=i;
    int lst;
    std::sort(s+1,s+n+1,cmp1);
    lst=0;
    for(int i=1;i<=n;++i){
        if(s[i].o==1){
            if(s[lst].x==s[i].x)link(s[lst].i,s[i].i),link(s[i].i,s[lst].i);
            lst=i;
        }else if(s[lst].x==s[i].x)link(s[lst].i,s[i].i);
    }
    std::sort(s+1,s+n+1,cmp2);
    lst=0;
    for(int i=1;i<=n;++i){
        if(s[i].o==2){
            if(s[lst].y==s[i].y)link(s[lst].i,s[i].i),link(s[i].i,s[lst].i);
            lst=i;
        }else if(s[lst].y==s[i].y)link(s[lst].i,s[i].i);
    }
    for(int i=1;i<=n;++i)
        if(s[i].o==3)
            for(int j=0;j<8;++j){
                std::pair<int,int>a=std::make_pair(s[i].x+dX[j],s[i].y+dY[j]);
                if(M.find(a)!=M.end())link(s[i].i,M[a]);
            }
    for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i);
    int ans=0;
    for(int i=1;i<=scc[0];++i)ans=std::max(ans,dp(i));
    printf("%d\n",ans);
    return 0;
}