题解:
对于同方向(横竖的),同行最近相邻的两个连边。每个关键点被左右最近横向点连边,被上下最近纵向点连边,*门按题意连,没有宝藏的点不连边,求强连通分量缩点后跑拓扑排序即可。
我打的好长啊。
AC Code:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define maxn 1000006
#define maxm 100005
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define F first
#define S second
using namespace std;
int n,r,c,cnt,in[maxm];
vector<int>h[maxn],z[maxn];
vector<pii>zy;
map<pii,int>st;
vector<int>G[maxm],V[maxm];
int sta[maxm],dfn[maxm],low[maxm],bl[maxm],siz[maxm],dis[maxm],scc,tim;
void dfs(int u){
dfn[u] = low[u] = ++tim;
sta[++sta[0]] = u;
for(int i=0,v;i<G[u].size();i++)
if(!dfn[v=G[u][i]]){
dfs(v);
low[u] = min(low[u] , low[v]);
}
else if(!bl[v]){
low[u] = min(low[u] , dfn[v]);
}
if(low[u] == dfn[u]){
scc++;
for(int t=-1;t!=u;){
bl[t = sta[sta[0]--]] = scc;
siz[scc]++;
}
}
}
int main(){
scanf("%d%d%d",&n,&r,&c);
for(int i=1;i<=n;i++){
int x,y,t;
scanf("%d%d%d",&x,&y,&t);
if(t == 1) h[x].pb(y);
if(t == 2) z[y].pb(x);
if(t == 3) zy.pb(mp(x,y));
st[mp(x,y)] = ++cnt;
}
for(int i=1;i<=r;i++)
if(!h[i].empty()){
sort(h[i].begin(),h[i].end());
for(int j=0,pr=0;j<h[i].size();j++){
int p = h[i][j];
if(j){
int npr = st[mp(i,p)];
G[npr].pb(pr),G[pr].pb(npr);
pr = npr;
}
else pr = st[mp(i,p)];
}
}
for(int i=1;i<=c;i++)
if(!z[i].empty()){
sort(z[i].begin(),z[i].end());
for(int j=0,pr=0;j<z[i].size();j++){
int p = z[i][j];
if(j){
int npr = st[mp(p,i)];
G[npr].pb(pr) , G[pr].pb(npr);
pr = npr;
}
else pr = st[mp(p,i)];
}
}
for(int i=0;i<zy.size();i++){
int p = st[zy[i]];
vector<int>::iterator t = lower_bound(h[zy[i].F].begin(),h[zy[i].F].end(),zy[i].S);
if(t != h[zy[i].F].end())
G[st[mp(zy[i].F,*t)]].pb(p);
if(t != h[zy[i].F].begin()){
t--;
G[st[mp(zy[i].F,*t)]].pb(p);
}
t = lower_bound(z[zy[i].S].begin(),z[zy[i].S].end(),zy[i].F);
if(t != z[zy[i].S].end())
G[st[mp(*t,zy[i].S)]].pb(p);
if(t != z[zy[i].S].begin()){
t--;
G[st[mp(*t,zy[i].S)]].pb(p);
}
for(int j=max(-1,1-zy[i].F);j<=min(1,r-zy[i].F);j++)
for(int k=max(-1,1-zy[i].S);k<=min(1,c-zy[i].S);k++)
if(j || k){
int u = zy[i].F + j , v = zy[i].S + k;
if(!st.count(mp(u,v))) continue;
G[p].pb(st[mp(u,v)]);
}
}
for(int i=1;i<=r;i++)
if(!h[i].empty()){
for(int j=0;j<h[i].size();j++){
int pp = h[i][j] , p = st[mp(i,pp)];
vector<int>::iterator t = lower_bound(z[pp].begin(),z[pp].end(),i);
if(t != z[pp].end())
G[st[mp(*t,pp)]].pb(p);
if(t != z[pp].begin())
t--,
G[st[mp(*t,pp)]].pb(p);
}
}
for(int i=1;i<=c;i++)
if(!z[i].empty()){
for(int j=0;j<z[i].size();j++){
int pp = z[i][j] , p = st[mp(pp,i)];
vector<int>::iterator t = lower_bound(h[pp].begin(),h[pp].end(),i);
if(t != h[pp].end())
G[st[mp(pp,*t)]].pb(p);
if(t != h[pp].begin())
t--,
G[st[mp(pp,*t)]].pb(p);
}
}
for(int i=1;i<=cnt;i++)
if(!dfn[i])
dfs(i);
for(int i=1;i<=cnt;i++)
for(int j=0,v;j<G[i].size();j++)
if(bl[i] != bl[v=G[i][j]])
V[bl[i]].pb(bl[v]) , in[bl[v]] ++;
queue<int>q;
for(int i=1;i<=scc;i++)
if(!in[i])
q.push(i) , dis[i] = siz[i];
int ans = 0;
for(int u;!q.empty();){
u = q.front() , q.pop();
ans = max(ans , dis[u]);
for(int j=0,v;j<V[u].size();j++){
in[v=V[u][j]] --;
dis[v] = max(dis[v] , dis[u] + siz[v]);
if(!in[v]) q.push(v);
}
}
printf("%d\n",ans);
}