【集训试题】exam 信心考 最小割
题意概述:
有N个人,A,B两个考场。如果学生i在A考场,总信心值增加xi;如果学生i在B考场,总信心值增加yi。其中还有m对好友,当第i对好友的两个人都在A考场时,总信心值增加ai;如果两人都在B考场,总信心值增加bi;如果两个人在不同考场,那么总信心值减少ci。
问总信心值最大能达到多少(总信心值的初始值为0)。
N<=10000,M<=50000,time limit = 1s
分析:
这类最小割问题非常经典,一般都是有两个集合,每个元素属于某个集合可以得到某种收益,同时还会有一些两个元素之间的关系,比如被分到同一个集合或者不同集合需要付出的代价/得到的收益等等。思路是首先我们将所有的收益全部加起来,假设我们得到了所有的收益,然后建图跑最小割求我们需要付出的最小代价,最大收益=所有可能的收益-最小代价。
说一下此题的建图,此题本身选择就可能产生代价,因此把代价看成收益。假设我们一开始从获得的总收益为,所有的x,y,a,b,c的和。
令s代表B考场,t代表A考场,s向所有考生连边容量为yi,当这条边被割掉的时候考生i被选入A考场,付出代价yi;所有考生向t连一条边容量为xi,意义同上;所有的朋友之间,s向两个点分别连边,容量为(b+c)/2,当这两条边被一起割掉的时候他们都在A考场,付出代价b+c;两个点向t连边,意义类似;两个点之间连一条容量为(a+b+2c)/2,当两个考生在不同考场的时候(在网络意义下他们不连通)这条边被割掉,这对朋友一共付出代价a+b+2c。
跑最小割即可,因为建图的时候涉及到除以二的问题所以先把所有的边容量乘以2,最后把这个2除回来即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
#define inf 9e18
using namespace std;
const int maxn=;
const int maxm=;
typedef long long LL; int N,M,A[maxn],B[maxn],S,T,tot;
struct data{ int u,v,a,b,c; }C[maxm];
struct net_edge{ int from,to,next; LL cap,flow; }NE[*maxn+*maxm];
int nfirst[maxn],nnp,cur[maxn],fl[maxn],d[maxn],gap[maxn];
int mq[maxn],front,rear; void _scanf(int &x)
{
x=;
char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
}
void data_in()
{
_scanf(N);_scanf(M);
for(int i=;i<=N;i++) _scanf(A[i]);
for(int i=;i<=N;i++) _scanf(B[i]);
for(int i=;i<=M;i++){
_scanf(C[i].u);_scanf(C[i].v);
_scanf(C[i].a);_scanf(C[i].b);_scanf(C[i].c);
}
}
void net_add_edge(int u,int v,LL cap)
{
NE[++nnp]=(net_edge){u,v,nfirst[u],cap,};
nfirst[u]=nnp;
NE[++nnp]=(net_edge){v,u,nfirst[v],,};
nfirst[v]=nnp;
}
void _net_add_edge(int u,int v,LL cap)
{
NE[++nnp]=(net_edge){u,v,nfirst[u],cap,};
nfirst[u]=nnp;
NE[++nnp]=(net_edge){v,u,nfirst[v],cap,};
nfirst[v]=nnp;
}
void build_net()
{
S=N+,T=N+,tot=T;
for(int i=;i<=N;i++){
net_add_edge(S,i,(LL)*B[i]);
net_add_edge(i,T,(LL)*A[i]);
}
int u,v;
for(int i=;i<=M;i++){
u=C[i].u,v=C[i].v;
net_add_edge(S,u,(LL)C[i].b+C[i].c);
net_add_edge(u,T,(LL)C[i].a+C[i].c);
net_add_edge(S,v,(LL)C[i].b+C[i].c);
net_add_edge(v,T,(LL)C[i].a+C[i].c);
_net_add_edge(u,v,(LL)C[i].a+C[i].b+(LL)*C[i].c);
}
}
void BFS(int s)
{
for(int i=;i<=tot;i++) d[i]=tot;
front=rear=;
mq[rear++]=s;
d[s]=;
int i,j;
while(front!=rear){
i=mq[front++];
for(int p=nfirst[i];p;p=NE[p].next){
j=NE[p].to;
if(d[j]==tot) d[j]=d[i]+,mq[rear++]=j;
}
}
}
LL augment(int s,int t)
{
int now=t; LL flow=inf;
while(now!=s){
flow=min(flow,NE[fl[now]].cap-NE[fl[now]].flow);
now=NE[fl[now]].from;
}
now=t;
while(now!=s){
NE[fl[now]].flow+=flow,NE[(fl[now]-^)+].flow-=flow;
now=NE[fl[now]].from;
}
return flow;
}
LL ISAP(int s,int t)
{
memcpy(cur,nfirst,sizeof(cur));
BFS(t);
for(int i=;i<=tot;i++) gap[d[i]]++;
LL maxflow=; int now=s,j;
while(d[s]<tot){
if(now==t){
maxflow+=augment(s,t);
now=s;
}
bool ok=;
for(int p=cur[now];p;p=NE[p].next){
j=NE[p].to;
if(d[j]+==d[now]&&NE[p].cap>NE[p].flow){
ok=;
cur[now]=fl[j]=p;
now=j;
break;
}
}
if(!ok){
int minl=tot;
for(int p=nfirst[now];p;p=NE[p].next){
j=NE[p].to;
if(d[j]+<minl&&NE[p].cap>NE[p].flow) minl=d[j]+;
}
if(--gap[d[now]]==) break;
gap[d[now]=minl]++;
cur[now]=nfirst[now];
if(now!=s) now=NE[fl[now]].from;
}
}
return maxflow;
}
void work()
{
build_net();
LL sum=;
for(int i=;i<=N;i++) sum+=A[i],sum+=B[i];
for(int i=;i<=M;i++)
sum+=C[i].a,sum+=C[i].b,sum+=C[i].c;
cout<<sum-ISAP(S,T)/<<'\n';
}
int main()
{
data_in();
work();
return ;
}
【集训试题】exam 信心考 最小割的更多相关文章
- [2016北京集训试题6]网络战争-[最小割树(网络流)+kd-tree+倍增]
Description A 联邦国有 N 个州,每个州内部都有一个网络系统,有若干条网络线路,连接各个 州内部的城市. 由于 A 国的州与州之间的关系不是太好,每个州都只有首府建立了到别的州的网络.具 ...
- LOJ6045 雅礼集训 2017 Day8 价(最小割)
由Hall定理,任意k种减肥药对应的药材数量>=k.考虑如何限制其恰好为k,可以将其看作是使对应的药材数量尽量少. 考虑最小割.建一个二分图,左边的点表示减肥药,右边的点表示药材.减肥药和其使用 ...
- LOJ_6045_「雅礼集训 2017 Day8」价 _最小割
LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...
- LOJ#6045. 「雅礼集训 2017 Day8」价(最小割)
题面 传送门 题解 首先先把所有权值取个相反数来求最大收益,因为最小收益很奇怪 然后建图如下:\(S\to\)药,容量\(\inf+p_i\),药\(\to\)药材,容量\(\inf\),药材\(\t ...
- P3749 [六省联考2017]寿司餐厅 最小割
\(\color{#0066ff}{ 题目描述 }\) Kiana 最近喜欢到一家非常美味的寿司餐厅用餐. 每天晚上,这家餐厅都会按顺序提供 \(n\) 种寿司,第 \(i\) 种寿司有一个代号 \( ...
- (2016北京集训十三)【xsy1532】网络战争 - 最小割树+树上倍增+KD树
题解: 好题!! 这题似乎能上我代码长度记录的前五? 调试时间长度应该也能上前五QAQ 首先题目要求的明显就是最小割,当然在整个森林上求Q次最小割肯定是会GG的,所以我们需要一个能快速求最小割的算法— ...
- P5934-[清华集训2012]最小生成树【最小割】
正题 题目链接:https://www.luogu.com.cn/problem/P5934 题目大意 给出\(n\)个点\(m\)条边的一张图,再加入一条边\((u,v,L)\)求至少删掉多少条边可 ...
- 最小割&网络流应用
重要链接 基础部分链接 : 二分图 & 网络流初步 zzz大佬博客链接 : 网络流学习笔记 重点内容:最小割二元关系新解(lyd's ppt) 题目:网络流相关题目 lyd神犇课件链接 : 网 ...
- 最大流&最小割 - 专题练习
[例1][hdu5889] - 算法结合(BFS+Dinic) 题意 \(N\)个点\(M\)条路径,每条路径长度为\(1\),敌人从\(M\)节点点要进攻\(1\)节点,敌人总是选择最优路径即最短路 ...
随机推荐
- ios appstore 上架应用被拒绝原因
ios appstore 上架应用被拒绝原因 应用程序崩溃 界面布局有明显错误挂羊头卖狗头的应用包括未公开的或隐藏功能的使用私有API应用程序读取或写入数据超出其指定的容器区域以任何方式下载代码的应用 ...
- django-orm简记
首先orm是什么? orm-------->对象关系映射 专业性解释网上一大推,随便搜搜就能了解大概.在我理解(通俗):一个类 ----- 数据库中一张表 类属性 ----- 数据表中的字段名 ...
- 大学C++程序设计教程期末复习重点
第一章 1.cin与count的应用<iostream> 例: cin>>a; cout<<"hello"<<endl; cout& ...
- 构建高可靠hadoop集群之3- Quorum Journal Manager
在正式环境中,搭建高可靠(ha)的系统是必须的. 例如oralce的rac,apache集群,windows服务器集群 本文不再赘言ha的重要性. 本文主要是对 http://hadoop.apach ...
- 如何在linux中创建虚拟环境
安装虚拟环境的命令 : sudo pip install virtualenv sudo pip install virtualenvwrapper 安装完虚拟环境后,如果提示找不到mkvirtual ...
- [Git add . ] 遇到The file will have its original line endings in your working directory 解决办法
1.在新项目中使用[ git add . ]时出现: warning: LF will be replaced by CRLF in ...... The file will have its ori ...
- 09 mongoDB基础(进阶)
mongoDB基础 阶段一.认识mongodb 1.mongodb 组织数据的基本形式 MongoDB————>数据库————>集合————>文档 mysql:表:行和列:字段 运用 ...
- 5.Python的语言特点
前言 Python有哪些语言特点?可以列出的特点很多,例如,<Python核心编程>第二版列出了十多条特点.本文的三个特点是笔者学习Python的体会,其他特点有体会之后再写,笔者是这 ...
- (数据科学学习手札15)DBSCAN密度聚类法原理简介&Python与R的实现
DBSCAN算法是一种很典型的密度聚类法,它与K-means等只能对凸样本集进行聚类的算法不同,它也可以处理非凸集. 关于DBSCAN算法的原理,笔者觉得下面这篇写的甚是清楚练达,推荐大家阅读: ht ...
- ArrayList底层原理
ArrayList底层采用数组实现,访问特别快,它可以根据索引下标快速找到元素.但添加插入删除等写操作效率低,因为涉及到内存数据复制转移. ArrayList对象初始化时,无参数构造器默认容量为10, ...