题面
https://www.luogu.org/problem/P2403
题解
我写的是让同一行、同一列的点形成一个环,表示它们互相可达。
$aysn$写的是对于同一行列建一个新点表示互相可达。
看了窝还是太弱了,还须多练。
#include<cstdio> #include<iostream> #include<cstring> #include<vector> #include<queue> #include<utility> #include<algorithm> #include<map> #define ri register int #define N 100500 using namespace std; const int dx[]={-1,-1,-1,0,0,1,1,1},dy[]={1,0,-1,1,-1,1,0,-1}; int n,r,c; int dfn[N],low[N],tot=0,inq[N],stk[N],top=0; int f[N]; int bel[N],cc=0; int x[N],y[N],t[N]; map<pair<int,int>,int> ot; vector<pair<int,int> > e; vector<int> about[N]; int val[N]; int idx[N],cntx=0,idy[N],cnty=0; vector<int> to[N]; void add_edge(int x,int y) { e.push_back(make_pair(x,y)); to[x].push_back(y); } bool cmpx(int a,int b) { return x[a]<x[b] ||(x[a]==x[b] && y[a]<y[b]); } bool cmpy(int a,int b) { return y[a]<y[b] ||(y[a]==y[b] && x[a]<x[b]); } void linkx() { sort(idx+1,idx+cntx+1,cmpx); for (ri i=1;i<=cntx;i++) { if (x[idx[i]]==x[idx[i+1]]) add_edge(idx[i],idx[i+1]); else { for (ri j=i;;j--) if (x[idx[j]]==x[idx[i]] && x[idx[j-1]]!=x[idx[i]]) { if (i!=j) add_edge(idx[i],idx[j]); break; } } } } void linky() { sort(idy+1,idy+cnty+1,cmpy); for (ri i=1;i<=cnty;i++) { if (y[idy[i]]==y[idy[i+1]]) add_edge(idy[i],idy[i+1]); else { for (ri j=i;;j--) if (y[idy[j]]==y[idy[i]] && y[idy[j-1]]!=y[idy[i]]) { if (i!=j) add_edge(idy[i],idy[j]); break; } } } } int prex(int i){ if (x[idx[i-1]]==x[idx[i]]) return i-1; for (ri j=i;;j++) if (x[idx[j]]==x[idx[i]]&&x[idx[j+1]]!=x[idx[i]]) return j; } void linkx2() { sort(idx+1,idx+cntx+1,cmpx); for (ri i=1;i<=cntx;i++) if (t[idx[i]]==1) { ri j=prex(i); while (t[idx[j]]!=1) { add_edge(idx[i],idx[j]); j=prex(j); } } } int prey(int i){ if (y[idy[i-1]]==y[idy[i]]) return i-1; for (ri j=i;;j++) if (y[idy[j]]==y[idy[i]]&&y[idy[j+1]]!=y[idy[i]]) return j; } void linky2() { sort(idy+1,idy+cnty+1,cmpy); for (ri i=1;i<=cnty;i++) if (t[idy[i]]==2) { ri j=prey(i); while (t[idy[j]]!=2) { add_edge(idy[i],idy[j]); j=prey(j); } } } void tarjan(int x) { dfn[x]=low[x]=++tot; inq[x]=1; stk[++top]=x; for (ri i=0,l=to[x].size();i<l;i++) { int y=to[x][i]; if (dfn[y] && !inq[y]) continue; if (!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); } else { low[x]=min(low[x],dfn[y]); } } if (low[x]==dfn[x]) { ++cc; int t; do { t=stk[top]; inq[t]=0; bel[t]=cc; top--; } while (t!=x); } } void makegraph() { for (ri i=1;i<=n;i++) val[bel[i]]++; int l=e.size(); for (ri i=0;i<l;i++) if (bel[e[i].first]!=bel[e[i].second]) about[bel[e[i].first]].push_back(bel[e[i].second]); } void dp(int x) { if (f[x]!=-1) return; f[x]=0; for (ri i=0,l=about[x].size();i<l;i++) { int y=about[x][i]; dp(y); if (f[y]>f[x]) f[x]=f[y]; } f[x]+=val[x]; } int main(){ scanf("%d %d %d",&n,&r,&c); for (ri i=1;i<=n;i++) { scanf("%d %d %d",&x[i],&y[i],&t[i]); ot[make_pair(x[i],y[i])]=i; } for (ri i=1;i<=n;i++) { if (t[i]==1) { idx[++cntx]=i; } else if (t[i]==2) { idy[++cnty]=i; } else if (t[i]==3) { for (ri j=0;j<8;j++) { int nx=x[i]+dx[j],ny=y[i]+dy[j]; if (ot.count(make_pair(nx,ny))) add_edge(i,ot[make_pair(nx,ny)]); } } } linkx(); linky(); for (ri i=1;i<=n;i++) { if (t[i]==1 || t[i]==3) { idy[++cnty]=i; } if (t[i]==2 || t[i]==3) { idx[++cntx]=i; } } linkx2(); linky2(); for (ri i=1;i<=n;i++) if (!dfn[i]) tarjan(i); makegraph(); memset(f,-1,sizeof(f)); int ans=0; for (ri i=1;i<=cc;i++) { dp(i); if (f[i]>ans) ans=f[i]; } cout<<ans<<endl; }