loj #2003. 「SDOI2017」新生舞会(分数规划+费用流)

来源:互联网 发布:ubuntu系统百度云 编辑:程序博客网 时间:2024/06/05 02:48

题目链接:https://loj.ac/problem/2003



代码:

#include<bits/stdc++.h>using namespace std;const int MAXN=500;const int MAXM=1e5+5;const int INF=0x3f3f3f3f;const double eps=1e-8;int a[105][105],b[105][105],n;namespace MCMF{struct Edge{int to,next,cap,flow;double cost;}edge[MAXM];int head[MAXN],tol;int pre[MAXN];double dis[MAXN];bool vis[MAXN];int N;//节点总个数,节点编号从0~N-1void init(int n){N=n;tol=0;memset(head,-1,sizeof(head));}void addedge(int u,int v,int cap,double cost){edge[tol].to=v;edge[tol].cap=cap;edge[tol].cost=cost;edge[tol].flow=0;edge[tol].next=head[u];head[u]=tol++;edge[tol].to=u;edge[tol].cap=0;edge[tol].cost=-cost;edge[tol].flow=0;edge[tol].next=head[v];head[v]=tol++;}bool spfa(int s,int t) { queue<int>q;for(int i=0;i<N;i++){dis[i]=INF;vis[i]=false;pre[i]=-1;}dis[s]=0;vis[s]=true;q.push(s);while(!q.empty()){int u=q.front();q.pop();vis[u]=false;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){dis[v]=dis[u]+edge[i].cost;pre[v]=i;if(!vis[v]){vis[v]=true;q.push(v);}}}}if(pre[t]==-1)return false;elsereturn true;}//返回的是最大流,cost存的是最小费用 int minCostMaxflow(int s,int t,double &cost){int flow=0;cost=0;while(spfa(s,t)){int Min=INF;for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){if(Min>edge[i].cap-edge[i].flow)Min=edge[i].cap-edge[i].flow;}for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){edge[i].flow+=Min;edge[i^1].flow-=Min;cost+=edge[i].cost*Min;}flow+=Min;}return flow;}}bool judge(double c){MCMF::init(2*n+2);for(int i=1;i<=n;i++){MCMF::addedge(0,i,1,0);for(int j=1;j<=n;j++){MCMF::addedge(i,n+j,1,-(a[i][j]-c*b[i][j]));}MCMF::addedge(n+i,n+n+1,1,0);}double cost=0;MCMF::minCostMaxflow(0,n+n+1,cost);return cost<eps;}int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);scanf("%d",&n);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){scanf("%d",&a[i][j]);}}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){scanf("%d",&b[i][j]);}}double l=0,r=100000,ans;int cnt=40;while(cnt--){double mid=(l+r)/2;if(judge(mid)){ans=mid;l=mid;}else{r=mid;}}printf("%.6lf\n",ans);return 0;}



阅读全文
0 0