bzoj 4819 [Sdoi2017]新生舞会
题面
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]新生舞会相关推荐
- BZOJ 4819: [Sdoi2017]新生舞会
二次联通门 : BZOJ 4819: [Sdoi2017]新生舞会 /*BZOJ 4819: [Sdoi2017]新生舞会二分 + 01分数规划 + 最小费用流二分出一个答案费用流检验*/ #incl ...
- 【BZOJ 4819】 4819: [Sdoi2017]新生舞会 (0-1分数规划、二分+KM)
4819: [Sdoi2017]新生舞会 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 601 Solved: 313 Description 学 ...
- BZOJ4819: [Sdoi2017]新生舞会
BZOJ4819: [Sdoi2017]新生舞会 Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴. 有n个男生和n个女生参加舞会买一个男生和一个女 ...
- [SDOI2017]新生舞会
题目描述 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴. 有个男生和个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴. Cathy收集了这些同学之间的关系,比如两个 ...
- BZOJ 4819 Luogu P3705 [SDOI2017]新生舞会 (最大费用最大流、二分、分数规划)
现在怎么做的题都这么水了.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=4819 (luogu) https://ww ...
- SDOI2017 新生舞会
01规划 a1+a2+a3+...+ai/b1+b2+b2+..bi最大 设一个k 使得 a1+a2+a3+...+ai/b1+b2+b3+...bi>=k 变换式子得到 a1+a2+a3+.. ...
- bzoj4819 [Sdoi2017]新生舞会 分数规划(实数二分)+网络流检验
这个题其实就是二分检验.. 稍微移个项就可以得到(a1-c*b1)+(a2-c*b2)+-- 这样贡献就化成了具体到每次决策的影响,c显然满足连续性,所以可以二分c 跑最大流以求得到最大的值使当前答案 ...
- codevs 5965 [SDOI2017]新生舞会
分数规划的裸题. 不会分数规划的OIer.百度:胡伯涛<最小割模型在信息学竞赛中的应用> /* TLE1: last:add(i,j+n,1e9,(real)((real)a[i][j]- ...
- 【BZOJ4819】【SDOI2017】新生舞会(01分数规划,带权二分图匹配)
Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的 ...
最新文章
- 【摩天好课】数字时代职业生涯规划
- 机器人学习--pitch yaw roll
- mysql中建立索引的原则_在SQL数据库中设定索引的原则是什么?(注意是设定不是创建)...
- 用canvas绘制一个圆形,实现绕着一个中心运动
- 读字库遇到坑爹的问题
- ETL异构数据源Datax_使用数据分片提升同步速度_05
- 做公益的飞秋(FeiQ)程序代码
- CCF201709-1 打酱油
- python echarts接口_Python之图表Pyecharts
- 怎么用python输入计算公式_如何从python3中的用户输入计算min和max
- Varnish的基本应用详解
- 凸优化有关的数值线性代数知识 作业题
- 协同过滤算法:在线推荐系统如何工作?
- 包子笔记 - 关于沉没成本
- Samsung SENS R60plus
- 智慧农业:各省市粮食产量排名,“鱼米之乡”湖南位居第十
- 一致性检验评价方法kappa
- 【磨刀不误砍柴工】由传递函数绘出频率响应图
- 给我“空降”一个弟兄
- 数学和计算机信息专业就业前景,数学专业就业方向和就业前景