传送门
我们首先可以用O(NlogN)的时间建出来所有的边。
然后我们大力tarjan求联通块
之后大力拓扑排序一发就可以了。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#define N 100005
#define M 1000005
using namespace std;
const int xxx[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
int head[N],head2[N],x[N],y[N],z[N],co[N];
int dfn[N],low[N],num[N],st[N],inq[N],mark[N],sum[N];
vector<int> a[M],b[M];
map<int,int> mp[M];
struct edge{int to,next;}e[M],ed[M];
int K,n,m,tot,top,color,tim,ans;
inline int read(){
int x=0;
char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar());
for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10-48+ch;
return x;
}
void ins(int x,int y){
if (x==y) return;
e[++tot].to=y;
e[tot].next=head[x];
head[x]=tot;
}
void ins2(int x,int y){
if (x==y) return;
ed[++tot].to=y;
ed[tot].next=head2[x];
head2[x]=tot;
}
void build(){
int p,t;
for (int i=1;i<=n;i++){
p=0;
t=a[i].size();
for (int j=0;j<t;j++)
if (z[a[i][j]]==1){p=a[i][j]; break;}
if (!p) continue;
for (int j=0;j<t;j++){
ins(p,a[i][j]);
if (z[a[i][j]]==1) ins(a[i][j],p);
}
}
for (int i=1;i<=m;i++){
p=0;
t=b[i].size();
for (int j=0;j<t;j++)
if (z[b[i][j]]==2){p=b[i][j]; break;}
if (!p) continue;
for (int j=0;j<t;j++){
ins(p,b[i][j]);
if (z[b[i][j]]==2) ins(b[i][j],p);
}
}
for (int i=1;i<=K;i++)
if (z[i]==3)
for (int j=0;j<8;j++){
t=mp[x[i]+xxx[j][0]][y[i]+xxx[j][1]];
if (t) ins(i,t);
}
}
void tarjan(int x){
dfn[x]=low[x]=++tim;
inq[x]=1;
st[++top]=x;
for (int i=head[x];i;i=e[i].next)
if (!dfn[e[i].to]){
tarjan(e[i].to);
low[x]=min(low[x],low[e[i].to]);
}
else if (inq[e[i].to])
low[x]=min(low[x],dfn[e[i].to]);
if (dfn[x]==low[x]){
int xx=0;
color++;
while (xx!=x){
xx=st[top--];
co[xx]=color;
inq[xx]=0;
num[color]++;
}
}
}
void rebuild(){
tot=0;
for (int i=1;i<=K;i++)
for (int j=head[i];j;j=e[j].next)
if (co[i]!=co[e[j].to]) ins2(co[i],co[e[j].to]);
}
void dp(int x){
mark[x]=1;
for (int i=head2[x];i;i=ed[i].next){
if (!mark[ed[i].to]) dp(ed[i].to);
sum[x]=max(sum[x],sum[ed[i].to]);
}
sum[x]+=num[x];
ans=max(ans,sum[x]);
}
int main(){
K=read(); n=read(); m=read();
for (int i=1;i<=K;i++){
x[i]=read();
y[i]=read();
z[i]=read();
mp[x[i]][y[i]]=i;
a[x[i]].push_back(i);
b[y[i]].push_back(i);
}
build();
for (int i=1;i<=K;i++)
if (!dfn[i]) tarjan(i);
rebuild();
for (int i=1;i<=color;i++)
if (!mark[i]) dp(i);
printf("%d",ans);
}