hdu 3395

来源:互联网 发布:企业数据集成 编辑:程序博客网 时间:2024/06/05 07:27
km()裸题题意:  有 n 条鱼,雄的会攻击他认为是雌的鱼,一条鱼一旦被攻击,就会生下一定数量的孩子,每条鱼只能被攻击一次,问最后最多可以生下多少孩子。分析: 因为每条鱼只能被攻击一次,正好符合二分图的性质,此题只要找出完全匹配下的最优匹配即可。#include<stdio.h>#include<string.h>#define inf 0x3fffffff#define N 200int n,link[N],mark[N],map[N][N],s[N],lx[N],ly[N];char str[N][N];int max(int a,int b){return a>b?a:b;}int min(int a,int b){return a<b?a:b;}int find(int k){int i;s[k]=1;for(i=1;i<=n;i++){if(!mark[i]&&lx[k]+ly[i]==map[k][i]){mark[i]=1;if(!link[i]||find(link[i])){link[i]=k;return 1;}}}return 0;}int km(){int sum=0,a,i,j,k;memset(lx,0,sizeof(lx));memset(ly,0,sizeof(ly));memset(link,0,sizeof(link));for(i=1;i<=n;i++)for(j=1;j<=n;j++)lx[i]=max(lx[i],map[i][j]);for(i=1;i<=n;i++){while(1){memset(s,0,sizeof(s));memset(mark,0,sizeof(mark));if(find(i))break;else{ a=inf;for(j=1;j<=n;j++){if(s[j]){for(k=1;k<=n;k++){if(!mark[k])a=min(a,lx[j]+ly[k]-map[j][k]);}}}for(j=1;j<=n;j++){if(s[j]) lx[j]-=a;if(mark[j]) ly[j]+=a;}}}}for(i=1;i<=n;i++){sum+=map[link[i]][i];}return sum;}int main(){int i,j,a[N];while(scanf("%d",&n),n!=0){for(i=1;i<=n;i++)scanf("%d",&a[i]);memset(map,0,sizeof(map));for(i=1;i<=n;i++)scanf("%s",str[i]+1);for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(str[i][j]=='1')//i!=j写不写都行map[i][j]=a[i]^a[j];printf("%d\n",km());}return 0;}//另外一种写法。#include<string.h>#include<stdio.h>#define N 110#define inf 0x3fffffffint map[N][N],lx[N],ly[N],sx[N],sy[N],n,d[N],cont[N],match[N];int find(int x){sx[x]=1;for(int i=0;i<n;i++){if(sy[i]==1)continue;int temp=lx[x]+ly[i]-map[x][i];if(temp==0){sy[i]=1;if(match[i]==-1||find(match[i])==1){match[i]=x;return 1;}}else d[i]=d[i]>temp?temp:d[i];}return 0;}int KM(){int i,j,k,sum,min;memset(match,-1,sizeof(match));memset(ly,0,sizeof(ly));for(i=0;i<n;i++){lx[i]=map[i][0];for(j=1;j<n;j++)if(lx[i]<map[i][j])lx[i]=map[i][j];}for(i=0;i<n;i++){for(j=0;j<n;j++)d[j]=inf;while(1){memset(sx,0,sizeof(sx));memset(sy,0,sizeof(sy));if(find(i)==1)break;min=inf;for(k=0;k<n;k++)if(sy[k]==0&&min>d[k])min=d[k];for(j=0;j<n;j++){if(sx[j]==1)lx[j]-=min;if(sy[j]==1)ly[j]+=min;}}}sum=0;for(i=0;i<n;i++)sum+=map[match[i]][i];return sum;}int main(){int i,j,k;char str[110];while(scanf("%d",&n)!=-1&&n){for(i=0;i<n;i++)scanf("%d",&cont[i]);memset(map,0,sizeof(map));for(i=0;i<n;i++){scanf("%s",str);for(j=0;j<n;j++)if(str[j]=='1')map[i][j]=cont[i]^cont[j];}k=KM();printf("%d\n",k);}return 0;}

0 0
原创粉丝点击