思路:缩点+拓扑dp
难点:建图,如果每一行全是横门或每一列全为纵门那就需要O(n^2)来建图,直接炸
那么我们不难找到性质:每一行的横门的集合为强连通分量,每一列的纵门的集合为强连通分量
那么将每一行(列)的强连通分量连为一个环即可
建边时可以先排序将横门放前,在将纵门放前,至于第三种门,直接建边即可
注意:建第三种边时我们应判断其四周是否有宝藏宫室,但是开不了int数组来存编号,于是干脆就将整个有编号的点存入哈希表中,找的时候就去搜那个点的哈希值所对应的编号是否为0,如果不为0,建边!!
剩下的就是跑一遍Tarjan缩点重新建图,再走一遍简单的拓扑dp即可
Code
#include<bits/stdc++.h>
#define re register
#define int long long
#define inl inline
using namespace std;
int read(){
int sum=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)){sum=(sum<<3)+(sum<<1)+(c^48);c=getchar();}
return sum*f;
}
const int mod=1e4+7;
const int N=1e7+10;
int n,m,x;
int cnt,top,dep,color;
int head[N],head2[N],stk[N],dis[N],dfn[N],low[N],siz[N],col[N],sum;
int ind[N];
std::queue<int> topu;
int dx[]={-1,0,1,0,1,1,-1,-1};
int dy[]={1,1,1,-1,0,-1,0,-1};
struct node{
int to,nxt;
}e[N<<1],r[N<<1];
struct Node{
int a,b,c,id;
}typ[N<<1];
map<int,int> mp;
bool cmp1(Node x,Node y){
if(x.a!=y.a) return x.a<y.a;
if(x.c==1) return 1;
if(y.c==1) return 0;
return x.b<y.b;
}
bool cmp2(Node x,Node y){
if(x.b!=y.b) return x.b<y.b;
if(x.c==2) return 1;
if(y.c==2) return 0;
return x.a<y.a;
}
void add(int x,int y){
e[++cnt].to=y;
e[cnt].nxt=head[x];
head[x]=cnt;
}
void add2(int x,int y){
r[++cnt].to=y;
r[cnt].nxt=head2[x];
head2[x]=cnt;
}
void tarjan(int u){
dfn[u]=low[u]=++dep;stk[++top]=u;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!col[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
color++;
col[u]=color;
siz[color]++;
while(stk[top]!=u){
siz[color]++;
col[stk[top--]]=color;
}
top--;
}
}
signed main(){
x=read(),n=read(),m=read();
for(int i=1;i<=x;i++){
typ[i].a=read();
typ[i].b=read();
typ[i].c=read();
typ[i].id=i;
mp[(typ[i].a-1)*m+typ[i].b]=typ[i].id;
}
//Hash();
sort(typ+1,typ+1+x,cmp1);
for(int i=1;i<=x;i++){
if(typ[i].c==1){
int fina=0;
int fi,la=0;
for(int j=i;j<=x&&typ[i].a==typ[j].a;j++){
fina=j;
if(typ[i].c==typ[j].c){
if(!la){
la=typ[j].id;
fi=la;
continue;
}
add(la,typ[j].id);
la=typ[j].id;
}
else add(typ[i].id,typ[j].id);
}
if(la!=fi){
add(la,fi);
}
i=fina;
}
}
sort(typ+1,typ+1+x,cmp2);
for(int i=1;i<=x;i++){
if(typ[i].c==2){
int fina=0;
int fi,la=0;
for(int j=i;j<=x&&typ[i].b==typ[j].b;j++){
fina=j;
if(typ[i].c==typ[j].c){
if(!la){
la=typ[j].id;
fi=la;
continue;
}
add(la,typ[j].id);
la=typ[j].id;
}
else add(typ[i].id,typ[j].id);
}
if(la!=fi){
add(la,fi);
}
i=fina;
}
}
for(int i=1;i<=x;i++){
if(typ[i].c!=3) continue;
for(int j=0;j<8;j++){
int xx=typ[i].a+dx[j];
int yy=typ[i].b+dy[j];
int p=mp[(xx-1)*m+yy];
if(!p) continue;
add(typ[i].id,p);
}
}
for(int i=1;i<=x;i++) if(!dfn[i]) tarjan(i);
cnt=0;
for(int i=1;i<=x;i++){
for(int j=head[i];j;j=e[j].nxt){
int v=e[j].to;
if(col[i]!=col[v]){
ind[col[v]]++;
add2(col[i],col[v]);
}
}
}
int ans=0;
for(int i=1;i<=color;i++){
if(!ind[i]) topu.push(i),dis[i]=siz[i],ans=max(ans,siz[i]);
}
while(topu.size()){
int u=topu.front();topu.pop();
for(int i=head2[u];i;i=r[i].nxt){
int v=r[i].to;
dis[v]=max(dis[v],dis[u]+siz[v]);
ans=max(ans,dis[v]);
ind[v]--;
if(!ind[v]) topu.push(v);
}
}
printf("%d\n",ans);
}