#include<cstdio>
#include<cstring>
const int MAXN=500;
const int MAXM=10000;
const int MAX=MAXM*2+MAXN*4+10;
const int INF=1;
int n,m;
int first[MAXN*2+3],k,next[MAX],head[MAX],tail[MAX],c[MAX],s,t;
int q[MAXN*2+3],qhead,qtail;
int d[MAXN*2+3];
int ans;
bool linked[MAXN*2+3][MAXN*2+3];
inline void open_file(void)
{
freopen("asteroid.in","r",stdin);
freopen("asteroid.out","w",stdout);
}
inline int getint(void)
{
int a;
scanf("%d",&a);
return a;
}
inline void addedge(int u,int v,int k,int w)
{
next[k]=first[u];
first[u]=k;
head[k]=u;
tail[k]=v;
c[k]=w;
}
inline void init(void)
{
n=getint();
m=getint();
s=n*2+1;
t=s+1;
for(int i=1;i<=m;i++)
{
int r=getint(),c=getint();
if(!linked[s][r])
{
k+=2;
addedge(s,r,k,1);
addedge(r,s,k^1,0);
linked[s][r]=true;
}
if(!linked[c+n][t])
{
k+=2;
addedge(c+n,t,k,1);
addedge(t,c+n,k^1,0);
linked[c+n][t]=true;
}
k+=2;
addedge(r,c+n,k,1);
addedge(c+n,r,k^1,0);
}
}
inline bool bfs(void)
{
memset(d,0,sizeof(d));
qhead=0;
qtail=0;
d[t]=1;
q[qtail++]=t;
while(qhead<qtail)
{
int u=q[qhead++];
for(int e=first[u];e;e=next[e])
{
int v=tail[e];
if(!d[v]&&c[e^1])
{
q[qtail++]=v;
d[v]=d[u]+1;
if(v==s)
return true;
}
}
}
return false;
}
int dfs(int u,int b)
{
if(u==t)
return b;
int r=0,tmp=0;
for(int e=first[u];e;e=next[e])
{
int v=tail[e];
if(d[v]<d[u]&&c[e])
{
tmp=dfs(v,(b-r)<c[e]?(b-r):c[e]);
c[e]-=tmp;
c[e^1]+=tmp;
r+=tmp;
}
}
return r;
}
inline void solve(void)
{
while(bfs())
{
ans+=dfs(s,INF);
}
}
inline void output(void)
{
printf("%d\n",ans);
}
inline void close_file(void)
{
fclose(stdin);
fclose(stdout);
}
int main(int argc,char *argv[])
{
open_file();
init();
solve();
output();
close_file();
return 0;
}
这道题吧,其实就是求一个二分图最小点覆盖。
根据定理,可知二分图最小点覆盖=二分图最大匹配=二分图最大流
所以吧,其实网络流就能做了。