思路:变形的最小路径覆盖,先用一次floyd求出每个点能去到的地方然后二分图匹配就好了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 505;
int n,m;
int mp[maxn][maxn];
struct Max_Match
{
int n;
vector<int>g[maxn];
bool vis[maxn];
int left[maxn];
void init(int n)
{
this->n=n;
for(int i = 0;i<=n;i++)g[i].clear();
memset(left,-1,sizeof(left));
}
bool match(int u)
{
for(int i = 0;i<g[u].size();i++)
{
int v = g[u][i];
if(!vis[v])
{
vis[v]=true;
if(left[v]==-1||match(left[v]))
{
left[v]=u;
return true;
}
}
}
return false;
}
int solve()
{
int ans = 0;
for(int i = 1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(match(i))++ans;
}
return ans;
}
}MM;
int main()
{
while(scanf("%d%d",&n,&m)!=EOF && (n+m))
{
MM.init(n);
for(int i = 0;i<=n;i++)
for(int j = 0;j<=n;j++)
mp[i][j]=1e9;
for(int i = 1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
mp[u][v]=1;
}
for(int k = 1;k<=n;k++)
for(int i = 1;i<=n;i++)
for(int j = 1;j<=n;j++)
if(mp[i][k]!=1e9 && mp[k][j]!=1e9)
mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=n;j++)
{
if(i==j)continue;
if(mp[i][j]!=1e9)
MM.g[i].push_back(j);
}
}
printf("%d\n",n-MM.solve());
}
}