bzoj 1143 二分图最大独立集
我们可以将一个点拆成两个点x,y,那么如果存在一条i->j的路径,我们就连接xi,yj,那么答案就是n-最大匹配数。
因为i->j所以对于i与j只能选一个,那么我们只需要求出来二分图的最大独立集就可以了,二分图的最大独立集=点数-最大匹配。
/************************************************************** Problem: 1143 User: BLADEVIL Language: C++ Result: Accepted Time:24 ms Memory:1636 kb ****************************************************************/ //By BLADEVIL #include <cstdio> #include <cstring> #define maxn 110 #define maxm 100100 using namespace std; int n,m,l,ans; int pre[maxm],other[maxm],last[maxn]; int flag[maxn],link[maxn],dis[maxn][maxn]; void connect(int x,int y) { pre[++l]=last[x]; last[x]=l; other[l]=y; //printf("%d %d\n",x,y); } int find(int x) { for (int p=last[x];p;p=pre[p]) { if (flag[other[p]]) continue; flag[other[p]]=1; if ((!link[other[p]])||find(link[other[p]])) { link[other[p]]=x; return 1; } } return 0; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); dis[x][y]=1; } for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int k=1;k<=n;k++) dis[j][k]|=dis[j][i]&dis[i][k]; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (i!=j) if (dis[i][j]) connect(i,j); ans=n; for (int i=1;i<=n;i++) { memset(flag,0,sizeof flag); if (find(i)) ans--; } printf("%d\n",ans); return 0; }