3 1 2 3 011 101 110 0
6
题意为有n条特殊的鱼,每个鱼都有一个价值,如果鱼i ”认为“ 鱼j 性别不同,那么就攻击它,繁殖的后代的价值为 v[i] ^ v[j], 每条鱼只能攻击或被攻击一次,问最后繁殖的后代的最大价值为多少。
也是比较裸的二分图最大权不匹配,边i,j的权值等于 v[i] ^ v[j] 。
http://blog.csdn.net/sr_19930829/article/details/40650359
代码:
#include <iostream> #include <stdio.h> #include <algorithm> #include <string.h> using namespace std; const int maxn=102; const int inf=0x3f3f3f; int nx,ny;//左右两边的点数 int v[maxn];//每条鱼的value int g[maxn][maxn];//邻接矩阵 int linked[maxn];//右边的点和左边哪个点连接 int lx[maxn],ly[maxn];//左右点的标号 int slack[maxn];//slack[j]表示右边的点j的所有不在导出子图的边对应的lx[i]+ly[j]-w[i][j]的最小值 bool visx[maxn],visy[maxn]; bool DFS(int x)//hungary求增广路 { visx[x]=true; for(int y=0;y<ny;y++) { if(visy[y]) continue; int tmp=lx[x]+ly[y]-g[x][y]; if(tmp==0) { visy[y]=true; if(linked[y]==-1||DFS(linked[y])) { linked[y]=x; return true; } } else if(slack[y]>tmp) slack[y]=tmp; } return false; } int KM() { memset(linked,-1,sizeof(linked)); memset(ly,0,sizeof(ly)); for(int i=0;i<nx;i++) { lx[i]=-inf; for(int j=0;j<ny;j++) if(g[i][j]>lx[i]) lx[i]=g[i][j]; } for(int x=0;x<nx;x++) { for(int y=0;y<ny;y++) slack[y]=inf; while(true) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(DFS(x)) break; int d=inf; for(int y=0;y<ny;y++) if(!visy[y]&&d>slack[y]) d=slack[y]; for(int i=0;i<nx;i++) if(visx[i]) lx[i]-=d; for(int i=0;i<ny;i++) { if(visy[i]) ly[i]+=d; else slack[i]-=d; } } } int ans=0; for(int y=0;y<ny;y++) { if(linked[y]!=-1) ans+=g[linked[y]][y]; } return ans; } int main() { int n; while(scanf("%d",&n)!=EOF&&n) { nx=ny=n; for(int i=0;i<n;i++) scanf("%d",&v[i]); int ch; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { scanf("%1d",&ch);//输入格式1d if(ch==1) g[i][j]=v[i]^v[j]; else g[i][j]=0; } } printf("%d\n",KM()); } return 0; }
[ACM] HDU 3395 Special Fish (二分图最大权匹配,KM算法)
原文:http://blog.csdn.net/sr_19930829/article/details/40650965