【JZOJ1156】【GDKOI2004】使命的召唤(二分图匹配)

Problem

  给定n(≤200)个机枪阵地,阵地i有两个整数xi,yi(0<=xi,yi<=30000)代表其坐标。给出m(≤30000)条连接两个阵地的路。一个敢死队员可以空降到任一个阵地上,炸掉一个阵地后,可以从当前阵地出发沿着路到达下一个x坐标比当前阵地大的阵地。
  注意:每个阵地都必须被摧毁,且每个阵地只能被经过一次。

Solution

  • 超级裸的二分图匹配。。。居然没想出来。。。
  • 把每个阵地拆成两个点。这样,就有两排点,每排n个点。
  • 如果阵地x能走到阵地y,则从左边的x连向右边的y。比如假如1能走到2,2能走到3;我们就从左边的1连向右边的2,左边的2连向右边的3。

  • 然后,直接上匈牙利算法/最大流求出最大匹配,ans即为n-匹配数。
  • 因为一开始每个阵地都要放敢死队员;但是如果我们用左边和1和右边的2匹配了,炸完阵地1的敢死队员就可以跑去炸阵地2,于是可以省一个人。
  • 因此,每匹配一组,就可以省一个人。

  • 时间复杂度: O(nm)or   O() O ( n m ) ( 匈 牙 利 ) o r       O ( 玄 ) ( 网 络 流 )

Code

#include <cstdio>
#include <cstring>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;

const int N=201;
int i,n,x[N],y,m,p,q,ans,res[N];
bool a[N][N],bz[N];

inline void link(int x,int y){a[x][y]=1;}

bool find(int x)
{
    int y;
    fo(y,1,n)
        if( a[x][y] && !bz[y] )
        {
            bz[y]=1;
            if( !res[y] || find(res[y]) )
            {
                res[y]=x;
                return 1;
            }
        }
    return 0;
}

int main()
{
    scanf("%d",&n);
    fo(i,1,n) scanf("%d%d",&x[i],&y);
    scanf("%d",&m);
    fo(i,1,m)
    {
        scanf("%d%d",&p,&q);
        if(x[p]<x[q]) link(p,q);
        else    
        if(x[p]>x[q]) link(q,p);
    }

    fo(i,1,n)
    {
        memset(bz,0,sizeof bz);
        ans+=find(i);
    }

    printf("%d",n-ans);
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值