HDU 3395 Special Fish【KM】

题意:  有 n 条鱼,雄的会攻击他认为是雌的鱼,一条鱼一旦被攻击,就会生下一定数量的孩子,每条鱼只能被攻击一次,

    问最后最多可以生下多少孩子。

分析: 因为每条鱼只能被攻击一次,正好符合二分图的性质,此题只要找出完全匹配下的最优匹配即可。

模板一:

View Code
#include<stdio.h>
#include<string.h>
#define INF 0x1f1f1f1f
int sx[101],sy[101];
int lx[101],ly[101];
char a[102][102];
int map[102][102];
int link[101];
int va[101];
int n,dmin;
int find(int x)
{
    int i,tmp;
    sx[x]=1;
    for(i=1;i<=n;i++)
    if(!sy[i])
    {
        tmp=lx[x]+ly[i]-map[x][i];
        if(tmp==0)
        {
            sy[i]=1;
            if(link[i]==0||find(link[i]))
            {
                link[i]=x;
                return 1;
            }
        }
        else if(tmp<dmin)
            dmin=tmp;
    }
    return 0;
}
int KM()
{
    int i,j,v,sum=0;
    for(i=1;i<=n;i++)
    {
        lx[i]=0;
        ly[i]=0;
        for(j=1;j<=n;j++)
        if(map[i][j]>lx[i])
            lx[i]=map[i][j];
    }
    memset(link,0,sizeof(link));
    for(v=1;v<=n;v++)
    {
        memset(sx,0,sizeof(sx));
        memset(sy,0,sizeof(sy));
        while(1)
        {
            dmin=INF;
            if(find(v))
             break;
            for(i=1;i<=n;i++)
            {
                if(sx[i]) {  lx[i]-=dmin;  sx[i]=0;  }
                if(sy[i]) {  ly[i]+=dmin;  sy[i]=0;  }
            }
        }
    }
    for(i=1;i<=n;i++)
        sum+=map[link[i]][i];
    return sum;
}
int main()
{
    int i,j;
    while(scanf("%d",&n),n)
    {
        for(i=1;i<=n;i++)
            scanf("%d",&va[i]);
        for(i=1;i<=n;i++)
        {
            scanf("%s",a[i]+1);
            for(j=1;j<=n;j++)
            {
                map[i][j]=a[i][j]-'0';
                if(map[i][j])
                    map[i][j]=va[i]^va[j];
            }
        }
        printf("%d\n",KM());
    }
    return 0;
}

 

 模板二:

View Code
#include<stdio.h>
#include<string.h>
#define INF 0x1f1f1f1f
#define clr(x)memset(x,0,sizeof(x))
int link[111];
int sx[111],sy[111];
int lx[111],ly[111];
char a[111][111];
int map[111][111];
int va[111];
int n;
int find(int x)
{
    int i;
    sx[x]=1;
    for(i=1;i<=n;i++)
    {
        if(!sy[i]&&lx[x]+ly[i]==map[x][i])
        {
            sy[i]=1;
            if(link[i]==0||find(link[i]))
            {
                link[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
int KM()
{
    int v,i,j,sum=0,dmin;
    for(i=1;i<=n;i++)
    {
        lx[i]=0;
        ly[i]=0;
        for(j=1;j<=n;j++)
            if(map[i][j]>lx[i])
            lx[i]=map[i][j];
    }
    clr(link);
    for(v=1;v<=n;v++)
    {
        clr(sx);  clr(sy);
        while(1)
        {
            if(find(v))break;
            dmin=INF;
            for(i=1;i<=n;i++)
            if(sx[i])
            for(j=1;j<=n;j++)
            if(!sy[j]&&lx[i]+ly[j]-map[i][j]<dmin)
                dmin=lx[i]+ly[j]-map[i][j];
            for(i=1;i<=n;i++)
            {
                if(sx[i]){  lx[i]-=dmin;   sx[i]=0;  }
                if(sy[i]){  ly[i]+=dmin;   sy[i]=0;  }
            }
        }
    }
    for(i=1;i<=n;i++)
        sum+=map[link[i]][i];
    return sum;
}
int main()
{
    int i,j;
    while(scanf("%d",&n),n)
    {
        memset(map,0,sizeof(map));
        for(i=1;i<=n;i++)
        scanf("%d",&va[i]);
        for(i=1;i<=n;i++)
        {
            scanf("%s",a[i]+1);
            for(j=1;j<=n;j++)
            if(a[i][j]=='1')
                map[i][j]=va[i]^va[j];
        }

        printf("%d\n",KM());
    }
    return 0;
}
posted @ 2012-04-30 18:51  'wind  阅读(261)  评论(0编辑  收藏  举报