1. 里面的判断向左,向右,向上扩展的条件成立要根据题目具体而定;
2. 注意边界问题
悬线法板子如下:
int n,m;
int a[maxn][maxn];
int up[maxn][maxn];
int l[maxn][maxn]; //i,j向左最大能扩展到哪个点
int r[maxn][maxn]; //i,j向右最大能扩展到哪个点
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
up[i][j] = 1; //初始化
l[i][j] = r[i][j] = j;
}
//预处理
for(int i=1;i<=n;i++)
for(int j=2;j<=m;j++) //向左扩展的条件成立,则更新向左扩展
if(check_l()) l[i][j] = l[i][j-1];
for(int i=1;i<=n;i++)
for(int j=m-1;j>=1;j--) //向右扩展的条件成立,则更新向右扩展
if(check_r()) r[i][j] = r[i][j+1];
ll ans1,ans2; //正方形面积,矩形面积
ans1 = ans2 = 0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(check_up()) //向上扩展的条件成立,则更新向上扩展
{
l[i][j] = max(l[i][j],l[i-1][j]); //收束一下
r[i][j] = min(r[i][j],r[i-1][j]);
up[i][j] = up[i-1][j] + 1;
}
int len = r[i][j] - l[i][j] + 1; //长
int hi = min(len,up[i][j]); //正方形的边长
ans1 = max(ans1,hi * hi); //正方形
ans2 = max(ans2,up[i][j] * len); //矩形
}
}
给一张图,计算连通块数量
注意: 1.建图时h[]初始化-1
2.数组开大点!!!
const int maxn = 2e5+7;
int a[maxn];
int vis[maxn];
int e[maxn*4],h[maxn*4],ne[maxn*4],idx;
int cnt; //连通块数量
vector<int> block[maxn]; //存每个连通块的点
邻接表
void dfs(int u,int cnt) //u为节点编号,cnt为连通块编号
{
vis[u] = 1; //记得标记
id[u] = cnt; //记录每个点所属的连通块
block[cnt].push_back(u); //这个连通块 存点的下标
for(int i = h[u];i != -1;i = ne[i])
{
int j = e[i];
if(!vis[j])
{
dfs(j,cnt);
}
}
}
//计算联通块的数量
for(int i = 1;i <= n;i++) //遍历每个点
{
if(!vis[i])
{
dfs(i,++cnt);
}
}
---------------------------------------分界线------------------------------------------
邻接矩阵
void dfs(int u,int bid) //bid为连通块的编号
{
if(u > n) return;
id[ids] = u;
block[ids].push_back(u);
for(i = u;i <= n;++i)
{
for(int j = u + 1;j <= n;++j)
{
if(!id[u] && g[i][j] == 1)
dfs(i,bid);
}
}
}
int cnt = 0; //连通块数量
for(int i = 1;i <= n;++i)
{
if(!id[i])
{
dfs(i,cnt++);
}
}
应该是在每一个 DFS之前把 根节点先给给标记上 防止后面的点搜 当前连通块中已经搜过的点
这里标记数组是不是忘记 写上了
完整的应该是这样的吧 我测了下 能过