★ HDU 3315 求KM最大时,要求改动最少
2014-07-26 21:36
447 查看
题意:S和X用神奇宝贝(形象化一下)打架,起初S的第si个和X的第xi个打,如果赢了加vi分,输了减vi分。现在要你在改动最少匹配的情况下,求出可以得到的最大的分数。
分析:和HDU 2853那题一样,但是这里的权值可能为负数,因此我们将每一条边的权值都加上1000,然后和HDU 2853的方法一样,将每条边的权值都乘以100,然后对原先已经匹配的边的权值都加1,求出最大匹配,判断即可。注意下,这题的实际数据范围比90大。。。坑。。。
代码:
分析:和HDU 2853那题一样,但是这里的权值可能为负数,因此我们将每一条边的权值都加上1000,然后和HDU 2853的方法一样,将每条边的权值都乘以100,然后对原先已经匹配的边的权值都加1,求出最大匹配,判断即可。注意下,这题的实际数据范围比90大。。。坑。。。
代码:
//其实在求最大 最小的时候只要用一个模板就行了,把边的权值去相反数即可得到另外一个.求结果的时候再去相反数即可 //邻接矩阵特别需要注意重边的问题,切记 #pragma comment(linker,"/STACK:102400000,102400000") #include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #include <vector> #include <string> #include <math.h> #include <queue> #include <stack> #include <map> #include <set> using namespace std; typedef long long ll; //记得必要的时候改成无符号 const int maxn=200; const int maxm=1000005; const int INF=1000000000; int n,nx,ny; int march[maxn],lx[maxn],ly[maxn],slack[maxn]; //lx,ly为顶标,nx,ny分别为x点集y点集的个数 int w[maxn][maxn]; bool visx[maxn],visy[maxn]; int fen[maxn],ha[maxn],hb[maxn]; int ta[maxn],tb[maxn]; int dfs(int x) { visx[x]=1; for(int y=1;y<=ny;y++) { if(visy[y]) continue; int t=lx[x]+ly[y]-w[x][y]; if(t==0) { visy[y]=1; if(march[y]==-1||dfs(march[y])) { march[y]=x; return 1; } } else if(slack[y]>t) //不在相等子图中slack 取最小的 slack[y]=t; } return 0; } int KM() { int i,j; memset(march,-1,sizeof(march)); memset(ly,0,sizeof(ly)); for(i=1;i<=nx;i++) //lx初始化为与它关联边中最大的 for(j=1,lx[i]=-INF;j<=ny;j++) if(w[i][j]>lx[i]) lx[i]=w[i][j]; for(int x=1;x<=nx;x++) { for(i=1;i<=ny;i++)slack[i]=INF; while(1) { memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); if(dfs(x)) //若成功(找到了增广轨),则该点增广完成,进入下一个点的增广 break; //若失败(没有找到增广轨),则需要改变一些点的标号,使得图中可行边的数量增加。 //方法为:将所有在增广轨中(就是在增广过程中遍历到)的X方点的标号全部减去一个常数d, //所有在增广轨中的Y方点的标号全部加上一个常数d int d=INF; for(i=1;i<=ny;i++) if(!visy[i]&&d>slack[i]) d=slack[i]; for(i=1;i<=nx;i++) if(visx[i]) lx[i]-=d; for(i=1;i<=ny;i++) //修改顶标后,要把所有不在交错树中的Y顶点的slack值都减去d if(visy[i]) ly[i]+=d; else slack[i]-=d; } } int res=0; for(i=1;i<=ny;i++){ if(march[i]>-1){ res+=w[march[i]][i]; } } return res; } int pd(int ha,int hb,int ta,int tb) { int x=0; while(1){ hb-=ta; x++; if(hb<=0)break; ha-=tb; x++; if(ha<=0)break; } if(x%2)return 1; return 0; } int main() { int s,t,i,j; while(~scanf("%d",&n)&&n) { for(i=1;i<=n;i++)scanf("%d",&fen[i]); for(i=1;i<=n;i++)scanf("%d",&ha[i]); for(i=1;i<=n;i++)scanf("%d",&hb[i]); for(i=1;i<=n;i++)scanf("%d",&ta[i]); for(i=1;i<=n;i++)scanf("%d",&tb[i]); for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if(pd(ha[i],hb[j],ta[i],tb[j])==1){ w[i][j]=fen[i]+1000; w[i][j]*=100; } else{ w[i][j]=1000-fen[i]; w[i][j]*=100; } } } for(i=1;i<=n;i++)w[i][i]+=1; nx=ny=n; s=t=KM(); t=t/100-n*1000; if(t<=0)printf("Oh, I lose my dear seaco!\n"); else{ printf("%d %.3f%%\n",t,(s%100)*1.0*100/n); } } return 0; }
相关文章推荐
- HDU 2853 Assignment([好题] 求KM最大时,要求改动最少★★)
- ★ HDU 2853 求KM最大时,要求改动最少
- HDU3315 My Brute (求KM最大时,要求改动最少★★)
- HDU 2853 Assignment 最大匹配+求最少改动的匹配数 之神奇建图
- HDU 3315 My Brute(KM最大匹配)
- HDU 3722 Card Game(KM最大匹配)
- HDU 3523 Image copy detection(KM最大匹配)
- hdu 1150 Machine Schedule 最少点覆盖转化为最大匹配
- Assignment (HDU 2853 最大权匹配KM)
- hdu 2929 有n根火柴, 要求组成一个七段数码组成的十进制数, 要求此数是m的倍数, 问此数最大为多少 DP
- hdu 1054 Strategic Game 最少点覆盖 二分图最大匹配
- HDU 3523 Image copy detection(KM最大匹配)
- hdu2853 Assignment (KM最少改动边)
- HDU 2853 Assignment(KM最大匹配好题)
- HDU 2853 Assignment(KM最大匹配好题)
- HDU 2282 Chocolate(KM最大匹配)
- hdu 3315 (KM,优先选择原来的匹配)
- hdu 2255二分图最大权值匹配的KM 算法
- HDU 3722 Card Game(KM最大匹配)
- HDU 2853 (KM最大匹配)