参见之前的vani和cl2捉迷藏。。代码都是一样的。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#define maxv 205
#define maxe 3005
#define inf 12345678
using namespace std;
struct edge
{
int v,f,nxt;
}e[maxe];
int map[maxv][maxv],n,m,x,y,s,t,nume=1,dis[maxv],g[maxv];
void addedge(int u,int v,int f)
{
e[++nume].v=v;
e[nume].f=f;
e[nume].nxt=g[u];
g[u]=nume;
e[++nume].v=u;
e[nume].f=0;
e[nume].nxt=g[v];
g[v]=nume;
}
bool bfs()
{
for (int i=1;i<=2*n+1;i++)
dis[i]=-1;
queue <int> q;
q.push(s);
dis[s]=0;
while (!q.empty())
{
int head=q.front();
q.pop();
for (int i=g[head];i;i=e[i].nxt)
{
int v=e[i].v;
if ((e[i].f>0) && (dis[v]==-1))
{
dis[v]=dis[head]+1;
q.push(v);
}
}
}
if (dis[t]==-1) return false;
return true;
}
int dinic(int x,int low)
{
if (x==t) return low;
int ret=0;
for (int i=g[x];low && i;i=e[i].nxt)
{
int v=e[i].v;
if ((dis[v]==dis[x]+1) && (e[i].f>0))
{
int dd=dinic(v,min(e[i].f,low));
e[i].f=e[i].f-dd;
e[i^1].f=e[i^1].f+dd;
low=low-dd;
ret=ret+dd;
}
}
if (ret==0) dis[x]=-1;
return ret;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
map[i][j]=inf;
for (int i=0;i<=2*n+1;i++)
g[i]=0;
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
map[x][y]=1;
}
for (int k=1;k<=n;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (map[i][j]>map[i][k]+map[k][j])
map[i][j]=map[i][k]+map[k][j];
s=0;t=2*n+1;
for (int i=1;i<=n;i++)
{
addedge(s,i,1);
addedge(i+n,t,1);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
if (map[i][j]!=inf)
addedge(i,j+n,1);
}
int max_flow=0;
while (bfs()==true)
max_flow=max_flow+dinic(s,inf);
printf("%d\n",n-max_flow);
return 0;
}