题目描述

  有\(n\)个物品,买第\(i\)个物品要花费\(a_i\)元。还有\(m\)对关系:同时买\(p_i,q_i\)两个物品会获得\(b_i\)点收益。

  设收益为\(B\),花费为\(A\),求\(\lceil\frac{B}{A}\rceil-1\)

  \(n\leq 400,m\leq 200000,1\leq a_i,b_i\leq 100\)

题解

  显然这是一个分数规划问题。

  二分答案\(s\),判断答案是否能大于\(s\)

\[\begin{align}
\frac{B}{A}&>s\\
B&>As\\
B-As&>0
\end{align}
\]

  问题转化成买一个物品获得\(-a_is\)点收益,求收益是否能\(>0\)

  显然这个可以用最大权闭合子图来做,点数为\(n+m+2\),边数为\(n+3m\),肯定会TLE

  考虑另一种连边方法。

  对于每个点\(i\),连边\((S,i,-a_is)\)

  对于每一对关系,列一个方程,解得:连边\((p_i,q_i,\frac{1}{2}b_i),(q_i,p_i,\frac{1}{2}b_i),(p_i,T,\frac{1}{2}b_i),(q_i,T,\frac{1}{2}b_i)\)。

  答案就是\(\sum_{i=1}^mb_i-maxflow\)

  因为容量为分数不好处理,所以可以把全部数\(\times 2\)。

  这样做的点数是\(n+2\),边数是\(2n+m\)。

  写ISAP不用卡常美滋滋。

代码

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
int rd()
{
int s=0,c;
while((c=getchar())<'0'||c>'9');
s=c-'0';
while((c=getchar())>='0'&&c<='9')
s=s*10+c-'0';
return s;
}
int sum=0;
namespace flow
{
int c[10000010];
int v[10000010];
int t[10000010];
int h[4010];
int n;
void add(int x,int y,int a)
{
n++;
v[n]=y;
c[n]=a;
t[n]=h[x];
h[x]=n;
}
void init()
{
memset(h,0,sizeof h);
n=0;
}
int S,T;
int num;
int d[4010];
int e[4010];
int cur[4010];
int op(int x)
{
return ((x-1)^1)+1;
}
queue<int> q;
void bfs()
{
memset(d,-1,sizeof d);
memset(e,0,sizeof e);
d[T]=0;
q.push(T);
int x,i;
while(!q.empty())
{
x=q.front();
q.pop();
e[d[x]]++;
for(i=h[x];i;i=t[i])
if(c[op(i)]&&d[v[i]]==-1)
{
d[v[i]]=d[x]+1;
q.push(v[i]);
}
}
}
int dfs(int x,int flow)
{
if(x==T)
return flow;
int s=0,u;
for(int &i=cur[x];i;i=t[i])
if(d[v[i]]==d[x]-1&&c[i])
{
u=dfs(v[i],min(flow,c[i]));
s+=u;
flow-=u;
c[i]-=u;
c[op(i)]+=u;
if(!flow)
return s;
}
e[d[x]]--;
if(!e[d[x]])
d[S]=num;
e[++d[x]]++;
cur[x]=h[x];
return s;
}
int solve()
{
bfs();
memcpy(cur,h,sizeof h);
int ans=0;
while(ans<2*sum&&d[S]>=0&&d[S]<=num-1)
ans+=dfs(S,2*sum-ans);
return ans;
}
}
using flow::S;
using flow::T;
using flow::num;
int n,m;
int lx[2000010];
int ly[2000010];
int lz[2000010];
int s[4010];
int a[4010];
void add(int x,int y,int z)
{
flow::add(x,y,z);
flow::add(y,x,0);
}
void add2(int x,int y,int z)
{
flow::add(x,y,z);
flow::add(y,x,z);
}
int check(int x)
{
flow::init();
int i;
S=n+1;
num=T=n+2;
for(i=1;i<=n;i++)
{
add(S,i,int(min(0x7fffffffll,2ll*a[i]*x)));
add(i,T,s[i]);
}
for(i=1;i<=m;i++)
if(lx[i]!=ly[i])
add2(lx[i],ly[i],lz[i]);
return flow::solve()<2*sum;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
#endif
// scanf("%d%d",&n,&m);
n=rd();
m=rd();
int i;
for(i=1;i<=n;i++)
// scanf("%d",&a[i]);
a[i]=rd();
for(i=1;i<=m;i++)
{
// scanf("%d%d%d",&lx[i],&ly[i],&lz[i]);
lx[i]=rd();
ly[i]=rd();
lz[i]=rd();
s[lx[i]]+=lz[i];
s[ly[i]]+=lz[i];
sum+=lz[i];
}
int l=0,r=sum;
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(mid))
l=mid;
else
r=mid-1;
}
printf("%d\n",l);
return 0;
}

【XSY2718】gift 分数规划 网络流的更多相关文章

  1. BZOJ2285 [SDOI2011]保密 【01分数规划 + 网络流】

    题目 现在,保密成为一个很重要也很困难的问题.如果没有做好,后果是严重的.比如,有个人没有自己去修电脑,又没有拆硬盘,后来的事大家都知道了. 当然,对保密最需求的当然是军方,其次才是像那个人.为了应付 ...

  2. gift 分数规划的最大权闭合子图

    题目大意: N个物品,物品间有M组关系,每个物品有一个ai的代价,满足关系后会得到bi的值 求 max(sigma(bi)/sigma(ai)) 题解: 很明显的最大权闭合子图,只不过需要处理分数. ...

  3. zju2676 Network Wars 分数规划+网络流

    题意:给定无向图,每条边有权值,求该图的一个割集,是的该割集的平均边权最小 Amber的<最小割模型在信息学竞赛中的应用>中讲的很清楚了. 二分答案k,对每条边进行重新赋值为原边权-k,求 ...

  4. bzoj 1312: Hard Life 01分数规划+网络流

    题目: Description 在一家公司中,人事部经理与业务部经理不和.一次,总经理要求人事部从公司的职员中挑选出一些来帮助业务部经理完成一项任务.人事部经理发现,在公司的所有职员中,有一些人相处得 ...

  5. 【BZOJ2285】[SDOI2011]保密(分数规划,网络流)

    [BZOJ2285][SDOI2011]保密(分数规划,网络流) 题面 BZOJ 洛谷 题解 首先先读懂题目到底在干什么. 发现要求的是一个比值的最小值,二分这个最小值\(k\),把边权转换成\(t- ...

  6. 【BZOJ3232】圈地游戏(分数规划,网络流)

    [BZOJ3232]圈地游戏(分数规划,网络流) 题面 BZOJ 题解 很神仙的一道题. 首先看到最大化的比值很容易想到分数规划.现在考虑分数规划之后怎么计算贡献. 首先每条边的贡献就变成了\(mid ...

  7. 【BZOJ4819】新生舞会(分数规划,网络流)

    [BZOJ4819]新生舞会(分数规划,网络流) 题面 BZOJ Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买 ...

  8. 【BZOJ3597】方伯伯运椰子(分数规划,网络流)

    [BZOJ3597]方伯伯运椰子(分数规划,网络流) 题解 给定了一个满流的费用流模型 如果要修改一条边,那么就必须满足流量平衡 也就是会修改一条某两点之间的路径上的所有边 同时还有另外一条路径会进行 ...

  9. bzoj 3232 圈地游戏——0/1分数规划(或网络流)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3232 当然是0/1分数规划.但加的东西和减的东西不在一起,怎么办? 考虑把它们合在一起.因为 ...

随机推荐

  1. itoa函数实现

    1.      整数字符转化为字符串数 // 将整数转换成字符串数,不用函数itoa // 思路:采用加'0',然后在逆序的方法 #include <iostream> using nam ...

  2. Oja’s rule

    目录 Oja's rule 背景 Hebbian learning 主要的一些理论 论文里面一些主要的假设 引理1 引理2 引理3 定理1 LEMMA 3(ALL) 引理 4 定理 2 定理 3(关于 ...

  3. 关于always块内for循环的执行方式

    //该模块主要用来说明for结构在时序逻辑中的执行方式 :] eq_dly ); integer i; 'b1; always @(posedge clk_1 or negedge nrst) beg ...

  4. semantic-ui 标题

    在semantic-ui中定义了5中标题样式,注意HTML中有h1-h6,而semantic-ui中只有h1-h5. 不过需要注意的是,semantic-ui的标题仍旧使用h1-h5来表示,但是在cl ...

  5. 硬盘扩容9999T

    win+r运行创建命令:subst H: d:\123说明:H指的是想要创建的盘符,d:\123是文件路径 删除命令subst H: d/说明 :H指的是已创建的盘符,/d指的是删除的意思 注意新盘符 ...

  6. iOS 10的两个坑

    iOS 10出现白屏幕,其他机型不会. 一个bug 手机连上电脑,在电脑端的Safari里,看到了如下的错误: SyntaxError: Cannot declare a let variable t ...

  7. 1 CHM 中文都是乱码

    CHM格式是Windows系统里常见的帮助文档格式,但有时一些CHM格式的文档会局部显示乱码,特别是一些外文文档在中文版Windows里.这是因为,CHM格式文档在Windows下默认是使用IE浏览器 ...

  8. jQuery EasyUI 折叠面板accordion的使用实例

    1.对折叠面板区域 div 设置 class=”easyui-accordion” 2.在区域添加多个 div, 每个 div 就是一个面板 (每个面板一定要设置 title 属性). 3.设置面板属 ...

  9. laravel实现批量添加数据

    在使用laravel eloquent进行数据库操作的时候惊讶的发现这货居然不支持批量添加,看到网上很多人在循环里进行数据库插入操作来实现批量添加,我想说这样做是很损失性能滴!好在框架的DB门面里的i ...

  10. jackson使用问题:mapper.readValue()将JSON字符串转反序列化为对象失败或异常

    问题根源:转化目标实体类的属性要与被转JSON字符串总的字段 一 一对应!字符串里可以少字段,但绝对不能多字段. 先附上我这段出现了问题的源码: // 1.接收并转化相应的参数.需要在pom.xml中 ...