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;
}

 

posted on 2014-05-07 09:12  BLADEVIL  阅读(590)  评论(0编辑  收藏  举报