bzoj 4819 [Sdoi2017]新生舞会
Description
学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴。有n个男生和n个女生参加舞会
买一个男生和一个女生一起跳舞,互为舞伴。Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出
a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度。Cathy还需要考虑两个人一起跳舞是否方便,
比如身高体重差别会不会太大,计算得出 b[i][j],表示第i个男生和第j个女生一起跳舞时的不协调程度。当然,
还需要考虑很多其他问题。Cathy想先用一个程序通过a[i][j]和b[i][j]求出一种方案,再手动对方案进行微调。C
athy找到你,希望你帮她写那个程序。一个方案中有n对舞伴,假设没对舞伴的喜悦程度分别是a'1,a'2,...,a'n,
假设每对舞伴的不协调程度分别是b'1,b'2,...,b'n。令
C=(a'1+a'2+...+a'n)/(b'1+b'2+...+b'n),Cathy希望C值最大。
Input
第一行一个整数n。
接下来n行,每行n个整数,第i行第j个数表示a[i][j]。
接下来n行,每行n个整数,第i行第j个数表示b[i][j]。
1<=n<=100,1<=a[i][j],b[i][j]<=10^4
Output
一行一个数,表示C的最大值。四舍五入保留6位小数,选手输出的小数需要与标准输出相等
Sample Input
3
19 17 16
25 24 23
35 36 31
9 5 6
3 4 2
7 8 9
19 17 16
25 24 23
35 36 31
9 5 6
3 4 2
7 8 9
Sample Output
5.357143
题解:
这题卡精度卡常卡到死哈.
建图很好想哈,i-j 容量为1 费用为a[i][j]-b[i][j]*mid 然后二分mid即可
注意邻接表不要开结构体,常数大的只能过50了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int N=203,inf=2e8,M=40505; 8 const double eps=1e-8; 9 double mapone[105][105],maptwo[105][105]; 10 int n,head[N],num=0; 11 int net[M],to[M],dis[M];double cost[M]; 12 void init(int x,int y,int dist,double costs){ 13 net[++num]=head[x];to[num]=y;dis[num]=dist;cost[num]=costs;head[x]=num; 14 } 15 void addedge(int x,int y,int dis,double cost){ 16 init(x,y,dis,cost);init(y,x,0,-cost); 17 } 18 int S=0,T,q[N*10],mod=N*10,pre[N];double f[N];bool vis[N];double st=0; 19 void updata(){ 20 int now=T,t; 21 while(now){ 22 t=pre[now]; 23 dis[t]--;dis[t^1]++; 24 now=to[t^1]; 25 } 26 st+=f[T]; 27 } 28 bool maxflow(){ 29 int x,u,t=0,sum=1; 30 for(int i=S;i<=T;i++)vis[i]=false,f[i]=-inf; 31 vis[S]=true;f[S]=0;q[1]=S; 32 while(t!=sum){ 33 t++;if(t==mod)t=0;x=q[t]; 34 for(int i=head[x];i;i=net[i]){ 35 u=to[i]; 36 if(dis[i]<=0)continue; 37 if(f[x]+cost[i]>f[u]){ 38 f[u]=f[x]+cost[i];pre[u]=i; 39 if(!vis[u]){ 40 vis[u]=true; 41 sum++;if(sum==mod)sum=0;q[sum]=u; 42 } 43 } 44 } 45 vis[x]=false; 46 } 47 if(f[T]==-inf || (st<eps && f[T]<eps))return false; 48 return true; 49 } 50 void Clear(){ 51 num=1;st=0; 52 memset(head,0,sizeof(head)); 53 } 54 bool check(double lim) 55 { 56 Clear(); 57 for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) 58 addedge(i,j+n,1,mapone[i][j]-maptwo[i][j]*lim); 59 for(int i=1;i<=n;i++)addedge(S,i,1,0),addedge(i+n,T,1,0); 60 while(maxflow())updata(); 61 return st>=eps; 62 } 63 void work() 64 { 65 scanf("%d",&n);T=n*2+1; 66 for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) 67 scanf("%lf",&mapone[i][j]); 68 for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) 69 scanf("%lf",&maptwo[i][j]); 70 double l=0,mid,ans,r=1e4; 71 while(l<=r-eps){ 72 mid=(l+r)/2; 73 if(check(mid))ans=mid,l=mid+eps; 74 else r=mid-eps; 75 } 76 printf("%.6lf\n",ans); 77 } 78 int main() 79 { 80 work(); 81 return 0; 82 }