博尔塔拉蒙古自治州网站建设_网站建设公司_Redis_seo优化
2026/1/17 13:42:39 网站建设 项目流程

Solution

不难发现我们只需要关心相邻的格子在什么时候相等,仅在相等时连边,然后找出现过的最大连通块。

设两个相邻格子分别为 \((i_1,j_1)\)\((i_2,j_2)\),相等时刻为 \(x\)。不难列出方程 \((v_{i_2,j_2}-v_{i_1,j_1})x=h_{i_1,j_1}-h_{i_2,j_2}\)

\(A=h_{i_1,j_1}-h_{i_2,j_2}\)\(B=v_{i_2,j_2}-v_{i_1,j_1}\)

  1. \(A=0\)\(B=0\),则两个格子高度永远相等,连边是永久边。
  2. \(A\neq0\)\(B=0\),无解。
  3. \(B\neq 0\)\(x\) 有唯一解,因此边是瞬时边。注意 \(x\) 必须 \(\ge 0\)

我们先处理出所有边,建一个并查集维护永久边形成的连通块并缩成点。再用第二个并查集维护这些新点之上的连通块。

然后将所有瞬时边按出现时刻排序后,每次将所有同一时刻出现的边加入第二个并查集并更新答案即可。但这样需要多次初始化第二个并查集,这可以用时间戳+懒标记 \(O(1)\) 实现。

浮点数可能会掉精度,最好手写分数存储时刻。

Code

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i(a);i<b;++i)
#define rept(i,a,b) for(int i(a);i<=b;++i)
#define int long long
#define il inline
using namespace std;
constexpr int N=701,S=N*N,dx[2]={0,1},dy[2]={1,0};
struct Frac{int a,b;Frac(int _a=0,int _b=1):a(_a),b(_b){int g=__gcd(a,b);a/=g,b/=g;if(b<0) a=-a,b=-b;}il bool operator<(const Frac &rhs) const {return a*rhs.b<rhs.a*b;}
};
struct Edge{int u,v;Frac t;il bool operator<(const Edge &rhs) const {return t<rhs.t;}
}e[S<<1];
int h[N][N],v[N][N];
int f1[S],s1[S];  // 第一个并查集
int f2[S],l2[S],s2[S],stamp;  // 第二个并查集
// l2:f2上一次被访问的时间
// stamp:当前时间戳(懒标记)
int n,m,ans;
int find1(int x){return x==f1[x]?x:f1[x]=find1(f1[x]);
}
int find2(int x){if(l2[x]<stamp){l2[x]=stamp;f2[x]=x;s2[x]=s1[x];}return x==f2[x]?x:f2[x]=find2(f2[x]);
}
il int calc(int i,int j){return n*(i-1)+j;
}
void solve(int l,int r){// e[l]~e[r]为出现在同一个时刻的边++stamp;rept(i,l,r){int u=find2(find1(e[i].u)),v=find2(find1(e[i].v));if(u^v){f2[u]=v;s2[v]+=s2[u];ans=max(ans,s2[v]);}}
}
signed main(){cin.tie(0)->sync_with_stdio(0);cin>>n;rept(i,1,n) rept(j,1,n) cin>>h[i][j];rept(i,1,n) rept(j,1,n) cin>>v[i][j];rept(i,1,n*n) f1[i]=i,s1[i]=1;rept(i,1,n){rept(j,1,n){rep(d,0,2){int di=i+dx[d];int dj=j+dy[d];int A=h[i][j]-h[di][dj];int B=v[di][dj]-v[i][j];if(!A&&!B){  // 永久边int u=find1(calc(i,j)),v=find1(calc(di,dj));if(u^v){f1[u]=v;s1[v]+=s1[u];ans=max(ans,s1[v]);}}else if(B){  // 瞬时边Frac t(A,B);if(t.a>=0) e[++m]={calc(i,j),calc(di,dj),t};}}}}sort(e+1,e+m+1);int l=1,r=1;for(int l=1,r=1;r<=m;){if(r==m||e[r].t<e[r+1].t){solve(l,r);l=r+1;}++r;}cout<<ans;return 0;
}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询