您的位置:首页 > 其它

HDU 4619 Warm up 2 (二分图最小覆盖集)

2016-02-14 15:58 435 查看
题意:给你两种纸牌 ,一种水平放置共有n张,一种竖直放置共有m张,他们被放在一个无限大的网格平面上。水平放置的纸牌占据点(x, y)和(x + 1 , y) , 竖直放置的纸牌占据点(x , y) 和 (x , y + 1)。水平放置的牌之间不会重叠,竖直放置的牌之间也不会重叠,但是水平放置的牌和竖直放置的牌之间可能会重叠。让你拿走一些牌,使剩下的牌之间不会重叠并且数量最多,输出剩余的最大牌数。

思路:把所有水平的骨牌放到二分图左点集,竖直骨牌放在二分图右点集.
如果左(水平)骨牌i与右(竖直)骨牌j有重叠部分,那么就在左i与右j之间连一条无向边. 所以新的二分图中每条边都代表了一个重叠的坐标位置.我们必须在每个重叠的位置上选择拿掉水平骨牌或是竖直骨牌来使得所有骨牌不重叠.(其实就是在二分图的左边或右边选每条边的端点抛弃).为了使得剩下的骨牌最多,我们移除的重叠骨牌必须最少,那么这个问题就是求二分图的最小覆盖集最终n+m-最小覆盖集数=
剩下的骨牌最大数目.

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=1000+50;

struct Max_Match
{
int n,m;
int g[maxn][maxn];
bool vis[maxn];
int left[maxn];

void init(int n,int m)
{
this->n=n;
this->m=m;
memset(left,-1,sizeof(left));
memset(g,0,sizeof(g));
}

bool match(int u)
{
for(int v=1;v<=m;v++)
{
if(g[u][v] && !vis[v])
{
vis[v]=true;
if(left[v]==-1 || match(left[v]))
{
left[v]=u;
return true;
}
}
}
return false;
}

int solve()
{
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(match(i)) ans++;
}
return ans;
}
}MM;
int T;
int cas = 1;
struct Node
{
int x1,y1;
int x2,y2;
Node(){}
Node(int x1,int y1,int x2,int y2):x1(x1),y1(y1),x2(x2),y2(y2){}
}node1[maxn],node2[maxn];
bool check(int i,int j)
{
if (node1[i].x1==node2[j].x1 && node1[i].y1==node2[j].y1)
return true;
else if (node1[i].x1 == node2[j].x2 && node1[i].y1==node2[j].y2)
return true;
else if (node1[i].x2==node2[j].x1 && node1[i].y2==node2[j].y1)
return true;
else if (node1[i].x2==node2[j].x2 && node1[i].y2==node2[j].y2)
return true;
return false;
}
int main()
{
int n,m;
while (scanf("%d%d",&n,&m)!=EOF && n)
{
MM.init(n,m);
for (int i = 1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
node1[i]=Node(x,y,x+1,y);
}
for (int i = 1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
node2[i]=Node(x,y,x,y+1);
}
for (int i = 1;i<=n;i++)
for (int j = 1;j<=m;j++)
{
if (check(i,j))
MM.g[i][j]=1;
}
printf("%d\n",n+m-MM.solve());
}
return 0;
}


Description

  Some 1×2 dominoes are placed on a plane. Each dominoe is placed either horizontally or vertically. It's guaranteed the dominoes in the same direction are not overlapped, but horizontal and vertical dominoes may overlap with each
other. You task is to remove some dominoes, so that the remaining dominoes do not overlap with each other. Now, tell me the maximum number of dominoes left on the board.

Input

  There are multiple input cases.

  The first line of each case are 2 integers: n(1 <= n <= 1000), m(1 <= m <= 1000), indicating the number of horizontal and vertical dominoes.

Then n lines follow, each line contains 2 integers x (0 <= x <= 100) and y (0 <= y <= 100), indicating the position of a horizontal dominoe. The dominoe occupies the grids of (x, y) and (x + 1, y).

  Then m lines follow, each line contains 2 integers x (0 <= x <= 100) and y (0 <= y <= 100), indicating the position of a horizontal dominoe. The dominoe occupies the grids of (x, y) and (x, y + 1).

  Input ends with n = 0 and m = 0.

Output

  For each test case, output the maximum number of remaining dominoes in a line.

Sample Input

2 3
0 0
0 3
0 1
1 1
1 3
4 5
0 1
0 2
3 1
2 2
0 0
1 0
2 0
4 1
3 2
0 0


Sample Output

4
6
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: