题目描述
题解
用floyed判断连通性。连通的两个点就可以匹配,然后求二分图的最大匹配就可以了。
刚开始直接在原图求最小路径覆盖的思路是错误的,因为不能保证覆盖的路径之间不存在连通关系。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=105;
const int max_m=max_n*max_n;
const int max_e=max_m;
int n,m,x,y,ans;
int tot,point[max_n],v[max_m],nxt[max_m];
int belong[max_n],vis[max_n];
bool a[max_n][max_n];
inline void addedge(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
}
inline int find(int x,int k){
for (int i=point[x]; i; i=nxt[i])
if (vis[v[i]]!=k){
vis[v[i]]=k;
if (!belong[v[i]]||find(belong[v[i]],k)){
belong[v[i]]=x;
return true;
}
}
return false;
}
inline void floyed()
{
for (int k=1;k<=n;++k)
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
a[i][j]|=a[i][k]&&a[k][j];
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
scanf("%d%d",&x,&y);
a[x][y]=true;
}
floyed();
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
if (i!=j&&a[i][j])
addedge(i,j);
for (int i=1;i<=n;++i)
if (find(i,i)) ans++;
printf("%d\n",n-ans);
}