比較顯然的縮點+拓撲排序題,只不過要建虛點優化建邊。git
首先咱們發如今一個SCC裏的點都是能夠一塊兒對答案產生貢獻的,所以先縮成DAG,而後拓撲找最長鏈。優化
可是咱們發現這題最壞狀況下邊數會達到恐怖的\(O(n^2)\),所以咱們能夠對於每種門進行討論:ui
而後每一個點對應橫縱座標的虛點都向這個點連邊,這樣就能夠處理同行/列的狀況。spa
不過這樣寫Tarjan就要注意常數問題了(點數邊數\(10000000+\)),手動卡常鬆鬆鬆code
CODE排序
#include<cstdio> #include<cctype> #include<map> #include<utility> #include<cstring> #define mp make_pair using namespace std; const int N=100005,R=1000005; const int fx[8]={0,1,0,-1,1,1,-1,-1},fy[8]={1,0,-1,0,1,-1,1,-1}; map <pair<int,int>,int> h; int n,r,c,cnt,head[N+(R<<1)],nhead[N+(R<<1)],dfn[N+(R<<1)],stack[N+(R<<1)],low[N+(R<<1)],s[N+(R<<1)],tot,scc,top,col[N+(R<<1)],ru[N+(R<<1)],d[N+(R<<1)],q[N+(R<<1)]; bool vis[N+(R<<1)]; struct data { int x,y,opt; }a[N]; struct edge { int to,next; }e[N<<3],ne[N<<3]; inline char tc(void) { static char fl[100000],*A=fl,*B=fl; return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++; } inline void read(int &x) { x=0; char ch; while (!isdigit(ch=tc())); while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc())); } inline void add(int x,int y) { e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt; } inline void nadd(int x,int y) { ne[++cnt].to=y; ne[cnt].next=nhead[x]; nhead[x]=cnt; } inline void build(int x,int y,int id) { for (register int i=0;i<8;++i) { int xx=x+fx[i],yy=y+fy[i]; if (xx>0&&xx<=r&&yy>0&&yy<=c&&h[mp(xx,yy)]) add(id,h[mp(xx,yy)]); } } inline void miner(int &x,int y) { if (y<x) x=y; } inline void maxer(int &x,int y) { if (y>x) x=y; } inline void Tarjan(int now) { dfn[now]=low[now]=++tot; stack[++top]=now; vis[now]=1; for (register int i=head[now];~i;i=e[i].next) if (!dfn[e[i].to]) Tarjan(e[i].to),miner(low[now],low[e[i].to]); else if (vis[e[i].to]) miner(low[now],dfn[e[i].to]); if (dfn[now]==low[now]) { col[now]=++scc; vis[now]=0; s[scc]=(now<=n); while (stack[top]!=now) col[stack[top]]=scc,vis[stack[top]]=0,s[scc]+=(stack[top--]<=n); --top; } } inline int top_sort(void) { register int i,H=0,T=0; int ans=0; for (i=1;i<=scc;++i) if (!ru[i]) q[++T]=i,d[i]=s[i]; while (H<T) { int now=q[++H]; maxer(ans,d[now]); for (i=nhead[now];~i;i=ne[i].next) { maxer(d[ne[i].to],d[now]+s[ne[i].to]); if (!(--ru[ne[i].to])) q[++T]=ne[i].to; } } return ans; } int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); register int i,j; read(n); read(r); read(c); memset(head,-1,sizeof(head)); memset(nhead,-1,sizeof(nhead)); for (i=1;i<=n;++i) { read(a[i].x); read(a[i].y); read(a[i].opt); switch (a[i].opt) { case 1:add(i,n+a[i].x);break; case 2:add(i,n+r+a[i].y);break; } add(n+a[i].x,i); add(n+r+a[i].y,i); h[mp(a[i].x,a[i].y)]=i; } for (i=1;i<=n;++i) if (a[i].opt==3) build(a[i].x,a[i].y,i); for (i=1;i<=n+r+c;++i) if (!dfn[i]) Tarjan(i); for (cnt=0,i=1;i<=n+r+c;++i) for (j=head[i];~j;j=e[j].next) if (col[i]!=col[e[j].to]) nadd(col[e[j].to],col[i]),++ru[col[i]]; return printf("%d",top_sort()),0; }