hdu3395 Special Fish (KM)

来源:互联网 发布:动态表单 数据库设计 编辑:程序博客网 时间:2024/05/18 01:25

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3395


题解:每只鱼最多只能攻击和被攻击一次,可能交配的鱼连一条边。


#include <stdio.h>        #include <string.h>       #include <math.h> #define INF 0x3f3f3f3f    #define MAXN 101  int w[MAXN][MAXN],match[MAXN],n;      int lx[MAXN],ly[MAXN],slack[MAXN];      int visitx[MAXN],visity[MAXN];   int find(int x)    {    int i,temp;    visitx[x]=1;    for(i=1;i<=n;++i)    {    if(visity[i])    continue;    temp=lx[x]+ly[i]-w[x][i];    if(temp==0)    {    visity[i]=1;    if(match[i]==-1||find(match[i]))    {    match[i]=x;//找到增广轨    return 1;    }    }    else if(slack[i]>temp)    {//不在相等子图中slack 取最小的    slack[i]=temp;    }    }    return 0;    }    int KM()    {    int i,j,d,ans;    memset(ly,0,sizeof(ly));    memset(match,-1,sizeof(match));    for(i=1;i<=n;++i)    {//lx初始化为与它关联边中最大的     lx[i]=w[i][1];    for(j=2;j<=n;++j)    if(w[i][j]>lx[i])    lx[i]=w[i][j];    }    for(i=1;i<=n;++i)    {    for(j=1;j<=n;++j)    slack[j]=INF;    while(1)    {    memset(visitx,0,sizeof(visitx));    memset(visity,0,sizeof(visity));    if(find(i))    break;    d=INF;    for(j=1;j<=n;++j)    {    if(!visity[j]&&d>slack[j])    d=slack[j];    }    for(j=1;j<=n;++j)    {    if(visitx[j])    lx[j]-=d;    if(visity[j])    ly[j]+=d;    else    slack[j]-=d;    }    }    } ans=0;for(i=1;i<=n;++i){if(match[i]!=-1)ans+=w[match[i]][i];}return ans;}  int main(){int i,j,ans,Value[MAXN];char ch[MAXN];while(scanf("%d",&n)&&n){memset(w,0,sizeof(w));for(i=1;i<=n;++i)scanf("%d",&Value[i]);for(i=1;i<=n;++i){scanf("%s",ch);for(j=1;j<=n;++j){if(ch[j-1]=='1')w[i][j]=Value[i]^Value[j];}}ans=KM();printf("%d\n",ans);}return 0;}


原创粉丝点击