HDU-1507-Uncle Tom's Inherited Land*(打印最大匹配路径)

题目

问题描述

你的汤姆叔叔从他的叔叔那里继承了一块土地。最初它是矩形的。然而,很久以前,他的叔叔决定把这块土地分成一个个小方格。他把一些广场变成池塘。(你不能肯定,因为你没有去过那个地方,但他可能造了很多池塘,现在这片土地可能由几个互不相连的岛屿组成。)
你的汤姆叔叔想卖掉继承来的土地。法律规定,房产只能以相当于你叔叔房产两个正方形大小的矩形地块出售。此外,池塘是不出售的财产。
你叔叔让你帮忙确定他能卖出去的最大数量的房产(剩下的广场将成为休闲公园)。
在这里插入图片描述

输入

输入将包括几个测试用例。测试用例的第一行包含两个整数N和M,分别表示土地的行数和列数(1 <= N, M <= 100)。第二行包含一个整数K,表示已经变成池塘的正方形的数量((N x M) - K <= 50)。接下来的K行每一行都包含两个整数X和Y,描述一个正方形变成池塘的位置(1 <= X <= N和1 <= Y <= M),输入的结束由N = M = 0表示。

输出

对于输入中的每个测试用例,您的程序应该首先输出一行,其中包含一个整数p,表示可以出售的属性的最大数量。接下来的p行指定可以同时出售的每对正方形。如果有多个解决方案,任何人都可以接受。在每个测试用例之后都有一个空白行。有关输出格式的说明,请参见下面的示例。

Sample Input

4 4
6
1 1
1 4
2 2
4 1
4 2
4 4
4 3
4
4 2
3 2
2 2
3 1
0 0

Sample Output

4
(1,2)–(1,3)
(2,1)–(3,1)
(2,3)–(3,3)
(2,4)–(3,4)

3
(1,1)–(2,1)
(1,2)–(1,3)
(2,3)–(3,3)

#include <cstdio>
#include <cstring>
#define m(a,b) memset(a,b,sizeof a)
using namespace std;
typedef long long ll;
const int N=1000010;
const int M=400010;
int tot,opo;
bool vis[N],used[1010][1010];
int my[N],mx[N],head[N];
struct Edge{int to,nex;}edge[M];
struct point{int x,y;}p[N];
void add(int from,int to)
{
    edge[++tot]=(Edge){to,head[from]};head[from]=tot;
}
bool find_path(int x)
{
    for(int i=head[x];i;i=edge[i].nex)
    {
        int y=edge[i].to;
        if(!vis[y])
        {
            vis[y]=1;
            if(!my[y]||find_path(my[y]))
            {
                my[y]=x;
                mx[x]=y;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m),n||m)
    {
        m(head,0);
        m(used,0);
        m(mx,0),m(my,0);
        tot=1,opo=0;
        int num;
        scanf("%d",&num);
        while(num--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            used[a][b]=1;
        }
        for(int i=1;i<=n;i++)
            for(int j=(i&1)?1:2;j<=m;j+=2)
            {
                if(used[i][j])
                    continue;
                p[++opo]=(point){i,j};      //将所有的偶数格子存起来。也就是二分图的左边。
                int a=(i-1)*m+j;
                if(i>=2&&!used[i-1][j])
                    add(a,a-m);
                if(i<=n-1&&!used[i+1][j])
                    add(a,a+m);
                if(j>=2&&!used[i][j-1])
                    add(a,a-1);
                if(j<=m-1&&!used[i][j+1])
                    add(a,a+1);
            }
        int ans=0;
        for(int i=1;i<=opo;i++)
        {
            m(vis,0);
            if(find_path((p[i].x-1)*m+p[i].y))
                ans++;
        }
        printf("%d\n",ans);
        for(int i=1;i<=opo;i++)
        {
            int np=mx[(p[i].x-1)*m+p[i].y];
            if(np)
            {
                int nx,ny;
                if(!(np%m))
                    nx=np/m,ny=m;
                else
                    nx=np/m+1,ny=np%m;
                printf("(%d,%d)--(%d,%d)\n",p[i].x,p[i].y,nx,ny);
            }
        }
        puts("");
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42576687/article/details/87900636