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,于是可以省一个人。
- 因此,每匹配一组,就可以省一个人。
- 时间复杂度:
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);
}