记录一个菜逼的成长。。
官方题解
题解里面貌似有错
这里应该还有条3->4的边
有人会问为什么会有2->4这条边,从图上看2的四个点都被覆盖了。
这就是建图时要注意的地方了,建图时我们只要根据两个矩形是否相交建图就可以了,不必去管矩形的四个点是否被覆盖。
因为虽然2的四个点都被覆盖,但是2是作为1和4之间的关联的。撕1时,会先撕去2,然后再撕去4.所以这里要有条2->4的边。这样在搜索时就不会漏了。
然后枚举第一次要撕去的海报,这里判断一下矩形的四个点是否被覆盖。
只要有一个点未被覆盖就可以直接去搜索了。
PS:这里我用y1数组不知道为什么会CE..说定义重了。然而程序里只定义了一次。。
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define cl(a,b) memset(a,b,sizeof(a))
const int maxn = 1000 + 10;
int x1[maxn],y11[maxn],x2[maxn],y2[maxn];
int f[maxn][4],vis[maxn];
vector<int>g[maxn];
int w,h,n;
bool overlap(int i, int j)
{
return !(x1[i] >= x2[j] || x1[j] >= x2[i] || y11[i] >= y2[j] || y11[j] >= y2[i]);
}
bool check(int i,int x,int y)
{
return x >= x1[i] && x <= x2[i] && y >= y11[i] && y <= y2[i];
}
int dfs(int x)
{
int ans = 0;
for( int i = 0; i < g[x].size(); i++ ){
if(!vis[g[x][i]]){
vis[g[x][i]] = 1;
ans += dfs(g[x][i]);
}
}
return ans + 1;
}
int main()
{
while(~scanf("%d%d%d",&w,&h,&n)){
for( int i = 1; i <= n; i++ ){
scanf("%d%d%d%d",&x1[i],&y11[i],&x2[i],&y2[i]);
}
for( int i = 1; i <= n; i++ ){
for( int j = i+1; j <= n; j++ ){
if(check(j,x1[i],y11[i]))f[i][0] = 1;
if(check(j,x1[i],y2[i]))f[i][1] = 1;
if(check(j,x2[i],y2[i]))f[i][2] = 1;
if(check(j,x2[i],y11[i]))f[i][3] = 1;
}
}
for( int i = 1; i <= n; i++ ){
for( int j = 1; j < i; j++ ){
if(overlap(i,j))g[j].pb(i);
}
}
int mx = -1;
int id;
for( int i = 1; i <= n; i++ ){
if(f[i][0] && f[i][1] && f[i][2] && f[i][3])continue;
cl(vis,0);
int ret = dfs(i);
if(ret > mx){
mx = ret;
id = i;
}
}
printf("%d %d\n",mx,id);
}
return 0;
}