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;

}

 

你可能感兴趣的:(二分图)