题面

https://www.lydsy.com/JudgeOnline/problem.php?id=4819

题解

这题很好想 首先二分答案 然后令w[i][j]=a[i][j]-b[i][j]*nwans

那么只要判断能否找出一个完美匹配 使得

KM算法或者费用流都可以做

Code

KM算法

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4
 5 ll read(){
 6     ll x=0,f=1;char c=getchar();
 7     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
 8     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
 9     return x*f;
10 }
11
12 const int maxn=110;
13 double w[maxn][maxn];    //边权
14 double la[maxn],lb[maxn];    //左右点的顶标
15 bool va[maxn],vb[maxn];    //访问标记(是否在交错树中)
16 int match[maxn];    //右部点匹配了哪一个左部点
17 int n;
18 double delta;
19
20 bool dfs(int x){
21     va[x]=1;
22     for(int y=1;y<=n;y++)
23         if(!vb[y])
24             if(fabs(la[x]+lb[y]-w[x][y])<=1e-8){    //相等子图
25                 vb[y]=1;
26                 if(!match[y] || dfs(match[y])){
27                     match[y]=x;
28                     return 1;
29                 }
30             }
31             else delta=min(delta,la[x]+lb[y]-w[x][y]);
32     return 0;
33 }
34
35 double KM(){
36     memset(match,0,sizeof(match));
37     for(int i=1;i<=n;i++){
38         la[i]=-(1<<30);
39         lb[i]=0;
40         for(int j=1;j<=n;j++)
41             la[i]=max(la[i],w[i][j]);
42     }
43     for(int i=1;i<=n;i++)
44         while(1){
45             memset(va,0,sizeof(va));
46             memset(vb,0,sizeof(vb));
47             delta=1<<30;
48             if(dfs(i)) break;
49             for(int j=1;j<=n;j++){
50                 if(va[j]) la[j]-=delta;
51                 if(vb[j]) lb[j]+=delta;
52             }
53         }
54     double ans=0;
55     for(int i=1;i<=n;i++)
56         ans+=w[match[i]][i];
57     return ans;
58 }
59
60 int a[maxn][maxn],b[maxn][maxn];
61
62 int main(){
63     #ifdef LZT
64     freopen("in","r",stdin);
65     #endif
66
67     n=read();
68     for(int i=1;i<=n;i++)
69         for(int j=1;j<=n;j++)
70             a[i][j]=read();
71     for(int i=1;i<=n;i++)
72         for(int j=1;j<=n;j++)
73             b[i][j]=read();
74     double l=0,r=1e4;
75     while(r-l>(1e-8)){
76         double md=(l+r)/2;
77         for(int i=1;i<=n;i++)
78             for(int j=1;j<=n;j++)
79                 w[i][j]=a[i][j]-b[i][j]*md;
80         if(KM()>=0) l=md;
81         else r=md;
82 //        cout<<l<<' '<<r<<endl;
83     }
84     printf("%.6f\n",l);
85     return 0;
86 }

View Code

费用流

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4
  5 ll read(){
  6     ll x=0,f=1;char c=getchar();
  7     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
  8     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
  9     return x*f;
 10 }
 11
 12 const int maxn=220,maxm=30200;
 13 int to[maxm],edge[maxm],nxt[maxm],head[maxn];
 14 double cost[maxm];
 15 double d[maxn];
 16 int pre[maxn],v[maxn],incf[maxn];
 17 //最短路长度,最小剩余容量,当前点在最短路中的前驱,是否访问过
 18 int n,k,tot,s,t,mxfl;
 19 double ans;
 20
 21 void add(int x,int y,int cap,double c){
 22     to[++tot]=y,edge[tot]=cap,cost[tot]=c,nxt[tot]=head[x],head[x]=tot;
 23     to[++tot]=x,edge[tot]=0,cost[tot]=-c,nxt[tot]=head[y],head[y]=tot;
 24 }
 25
 26 bool spfa(){
 27     queue<int> q;
 28     memset(d,0xcf,sizeof(d));    //-INF
 29     memset(v,0,sizeof(v));
 30     q.push(s);
 31     d[s]=0,v[s]=1;
 32     incf[s]=1<<30;
 33     while(!q.empty()){
 34         int x=q.front();q.pop();
 35         v[x]=0;
 36         for(int i=head[x];i;i=nxt[i]){
 37             if(edge[i]==0) continue;    //容量为0
 38             int y=to[i];
 39             if(d[y]<d[x]+cost[i]){
 40                 d[y]=d[x]+cost[i];    //这里是最大费用最大流
 41                 incf[y]=min(incf[x],edge[i]);
 42                 pre[y]=i;    //记录前驱,方便递归找最短路
 43                 if(!v[y]) v[y]=1,q.push(y);
 44             }
 45         }
 46     }
 47     if(d[t]==d[t+1]) return false;
 48     return true;
 49 }
 50
 51 //更新最长增广路及其反向边的剩余容量
 52 void update(){
 53     int x=t;
 54     while(x!=s){
 55         int ind=pre[x];
 56         edge[ind]-=incf[t];
 57         edge[ind^1]+=incf[t];
 58         x=to[ind^1];
 59     }
 60     mxfl+=incf[t];
 61     ans+=d[t]*incf[t];
 62 }
 63
 64 double calc(){
 65     while(spfa()) update();
 66     return ans;
 67 }
 68
 69 int a[110][110],b[110][110];
 70 double w[110][110];
 71
 72 int main(){
 73     #ifdef LZT
 74     freopen("in","r",stdin);
 75     #endif
 76     n=read();
 77     for(int i=1;i<=n;i++)
 78         for(int j=1;j<=n;j++)
 79             a[i][j]=read();
 80     for(int i=1;i<=n;i++)
 81         for(int j=1;j<=n;j++)
 82             b[i][j]=read();
 83     s=n+n+1,t=n+n+2;
 84     double l=0,r=1e4;
 85     while(r-l>(1e-8)){
 86         double md=(l+r)/2;
 87         for(int i=1;i<=n;i++)
 88             for(int j=1;j<=n;j++)
 89                 w[i][j]=a[i][j]-b[i][j]*md;
 90         tot=1;
 91         memset(head,0,sizeof(head));
 92         memset(nxt,0,sizeof(nxt));
 93         for(int i=1;i<=n;i++)
 94             add(s,i,1,0),add(i+n,t,1,0);
 95         for(int i=1;i<=n;i++)
 96             for(int j=1;j<=n;j++)
 97                 add(i,j+n,1,w[i][j]);
 98         mxfl=ans=0;
 99         calc();
100         if(ans>=1e-8) l=md;
101         else r=md;
102     }
103     printf("%.6f\n",l);
104     return 0;
105 }

View Code

好像还是KM跑的快一点而且代码短一点

转载于:https://www.cnblogs.com/wawawa8/p/9356429.html

bzoj 4819 [Sdoi2017]新生舞会相关推荐

  1. BZOJ 4819: [Sdoi2017]新生舞会

    二次联通门 : BZOJ 4819: [Sdoi2017]新生舞会 /*BZOJ 4819: [Sdoi2017]新生舞会二分 + 01分数规划 + 最小费用流二分出一个答案费用流检验*/ #incl ...

  2. 【BZOJ 4819】 4819: [Sdoi2017]新生舞会 (0-1分数规划、二分+KM)

    4819: [Sdoi2017]新生舞会 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 601  Solved: 313 Description 学 ...

  3. BZOJ4819: [Sdoi2017]新生舞会

    BZOJ4819: [Sdoi2017]新生舞会 Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴. 有n个男生和n个女生参加舞会买一个男生和一个女 ...

  4. [SDOI2017]新生舞会

    题目描述 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴. 有个男生和个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴. Cathy收集了这些同学之间的关系,比如两个 ...

  5. BZOJ 4819 Luogu P3705 [SDOI2017]新生舞会 (最大费用最大流、二分、分数规划)

    现在怎么做的题都这么水了.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=4819 (luogu) https://ww ...

  6. SDOI2017 新生舞会

    01规划 a1+a2+a3+...+ai/b1+b2+b2+..bi最大 设一个k 使得 a1+a2+a3+...+ai/b1+b2+b3+...bi>=k 变换式子得到 a1+a2+a3+.. ...

  7. bzoj4819 [Sdoi2017]新生舞会 分数规划(实数二分)+网络流检验

    这个题其实就是二分检验.. 稍微移个项就可以得到(a1-c*b1)+(a2-c*b2)+-- 这样贡献就化成了具体到每次决策的影响,c显然满足连续性,所以可以二分c 跑最大流以求得到最大的值使当前答案 ...

  8. codevs 5965 [SDOI2017]新生舞会

    分数规划的裸题. 不会分数规划的OIer.百度:胡伯涛<最小割模型在信息学竞赛中的应用> /* TLE1: last:add(i,j+n,1e9,(real)((real)a[i][j]- ...

  9. 【BZOJ4819】【SDOI2017】新生舞会(01分数规划,带权二分图匹配)

    Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的 ...

最新文章

  1. 【摩天好课】数字时代职业生涯规划
  2. 机器人学习--pitch yaw roll
  3. mysql中建立索引的原则_在SQL数据库中设定索引的原则是什么?(注意是设定不是创建)...
  4. 用canvas绘制一个圆形,实现绕着一个中心运动
  5. 读字库遇到坑爹的问题
  6. ETL异构数据源Datax_使用数据分片提升同步速度_05
  7. 做公益的飞秋(FeiQ)程序代码
  8. CCF201709-1 打酱油
  9. python echarts接口_Python之图表Pyecharts
  10. 怎么用python输入计算公式_如何从python3中的用户输入计算min和max
  11. Varnish的基本应用详解
  12. 凸优化有关的数值线性代数知识 作业题
  13. 协同过滤算法:在线推荐系统如何工作?
  14. 包子笔记 - 关于沉没成本
  15. Samsung SENS R60plus
  16. 智慧农业:各省市粮食产量排名,“鱼米之乡”湖南位居第十
  17. 一致性检验评价方法kappa
  18. 【磨刀不误砍柴工】由传递函数绘出频率响应图
  19. 给我“空降”一个弟兄
  20. 数学和计算机信息专业就业前景,数学专业就业方向和就业前景

热门文章

  1. web应用存在的10大安全问题,安全测试不容忽视!
  2. 聚类算法中 K均值聚类(KMeans)的python实现
  3. qlserver、Mysql、Oracle三种数据库的优缺点总结
  4. cesium 建筑物加载(带高度)
  5. WSL2 启用systemd
  6. win10 mrt 找不到
  7. 三维匹配_三维GIS数据融合的基本方法与进展
  8. Chrome调试工具(CSS)
  9. 分享几个CDN加速服务
  10. 【NLP文本分类】对IMDB电影评论进行情感分析