标签:ble 调度 答案 gif 分数规划 clu print 二分 names
题意:
有n个男生和n个女生参加舞会,一个男生和一个女生互为舞伴。
已知第i个男生与第j个女生跳舞会产生$a_{i,j}$的喜悦度和$b_i,j$的不协调度。
你希望最终配对方案的$\frac{\sum{a_{i,j} }}{\sum{b_{i,j} }}$最大,求这个最大值。
$n\leq 100,1\leq a_{i,j},b_{i,j}\leq 10000$。
题解:
求一个最大化的比值基本就是分数规划了。
于是二分答案k,问题变为判断是否存在$\sum{a_{i,j}-k\times b_{i,j}}\geq 0$的方案。
显然直接跑个最大费用二分图匹配即可。
复杂度$O(m\sqrt{n} \log{k})$。
套路:
代码:
#include<bits/stdc++.h> #define maxn 505 #define maxm 1000005 #define inf 0x7fffffff #define eps 1e-10 #define ll long long #define rint register int #define debug(x) cerr<<#x<<": "<<x<<endl #define fgx cerr<<"--------------"<<endl #define dgx cerr<<"=============="<<endl using namespace std; int n,nxt[maxm],hd[maxn],to[maxm],fl[maxm]; double A[maxn][maxn],B[maxn][maxn]; double cst[maxm],dis[maxn],Cost; int inq[maxn],vis[maxn],cnt,S,T; queue<int> q; inline int read(){ int x=0,f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘; return x*f; } inline void addedge(int u,int v,int w,double c){ to[++cnt]=v,fl[cnt]=w,cst[cnt]=c,nxt[cnt]=hd[u],hd[u]=cnt; to[++cnt]=u,fl[cnt]=0,cst[cnt]=-c,nxt[cnt]=hd[v],hd[v]=cnt; } inline bool spfa(){ for(int i=1;i<=T;i++) dis[i]=2e9; q.push(S),inq[S]=1,dis[S]=0; while(!q.empty()){ int u=q.front(); q.pop(),inq[u]=0; for(int i=hd[u];i;i=nxt[i]){ int v=to[i]; if(fl[i]>0 && dis[v]>dis[u]+cst[i]){ dis[v]=dis[u]+cst[i]; if(!inq[v]) q.push(v),inq[v]=1; } } } return dis[T]<2e9; } inline int dfs(int u,int flow){ if(u==T) return flow; vis[u]=1; int sum=0; for(int i=hd[u];i;i=nxt[i]){ int v=to[i]; if(vis[v] || fl[i]<=0 || dis[v]!=dis[u]+cst[i]) continue; int f=dfs(v,min(flow,fl[i])); flow-=f,sum+=f,Cost+=f*cst[i],fl[i]-=f,fl[i^1]+=f; if(!flow) break; } if(!sum) dis[u]=2e9; return sum; } inline double Dinic(){ Cost=0; while(spfa()) memset(vis,0,sizeof(vis)),dfs(S,inf); return Cost; } inline bool check(double k){ memset(hd,0,sizeof(hd)),cnt=1; for(int i=1;i<=n;i++) addedge(S,i,1,0),addedge(i+n,T,1,0); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) addedge(i,j+n,1,k*B[i][j]-A[i][j]); return Dinic()<eps; } int main(){ n=read(),S=2*n+1,T=2*n+2; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) A[i][j]=read(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) B[i][j]=read(); double l=0,r=10000; while(l+eps<r){ double mid=(l+r)/2.0; check(mid)?l=mid:r=mid; } printf("%.6lf\n",l); return 0; }
标签:ble 调度 答案 gif 分数规划 clu print 二分 names
原文地址:https://www.cnblogs.com/YSFAC/p/13217350.html