【BZOJ】【3550】【ONTAK2010】Vacation
网络流/费用流
Orz太神犇了这题……
我一开始想成跟Intervals那题一样了……每个数a[i]相当于覆盖了(a[i]-n,a[i]+n)这个区间……但是这样是错的!!随便就找出反例了……我居然还一直当正解……
实际上刚刚那个思路还有一个问题:题目中的长度为N的区间指的是给的原序列!而不是权值的区间!题就理解错了……
看了下zyf的题解,才明白过来,要用跟志愿者招募一样的方法来做;另外,志愿者招募时每种志愿者是有无限多名的,但这题中每个数只能选一次,所以边权为a[i]的边的流量不能是INF,而是1。
题解:做这题真是一种折磨。。。复习了一下根据流量平衡方程建图的方法,主要是膜拜了byvoid的志愿者招募的题解。。。让我们先列出流量平衡方程:a[i]表示i选不选,b[i]表示第i个等式的辅助变量则:0=0a[1]+a[2]+……a[n]+b[1]=ka[2]+a[3]+……a[n+1]+b[2]=k…………a[2*n+1]+a[2*n+2]+……+a[3*n]+b[2*n+1]=k0=0差分之后是a[1]+a[2]+……a[n]+b[1]=ka[n+1]-a[1]+b[2]-b[1]=0a[n+2]-a[2]+b[3]-b[2]=0…………-a[2*n+1]-a[2*n+2]-………-a[3*n]-b[2*n+1]=-k根据BYVOID所说的这段话:可以发现,每个等式左边都是几个变量和一个常数相加减,右边都为0,恰好就像网络流中除了源点和汇点的顶点都满足流量平衡。每个正的变量相当于流入该顶点的流量,负的变量相当于流出该顶点的流量,而正常数可以看作来自附加源点的流量,负的常数是流向附加汇点的流量。因此可以据此构造网络,求出从附加源到附加汇的网络最大流,即可满足所有等式。而我们还要求最小,所以要在X变量相对应的边上加上权值,然后求最小费用最大流。
所以我们构图:s=0;t=3*n+1;
for1(i,3*n)a[i]=read();
insert(s,1,k,0);insert(2*n+2,t,k,0);
for1(i,n)insert(1,i+1,1,-a[i]);
for2(i,n+1,2*n)insert(i-n+1,i+1,1,-a[i]);
for2(i,2*n+1,3*n)insert(i-n+1,2*n+2,1,-a[i]);
for1(i,2*n+1)insert(i,i+1,inf,0);需要搞清楚a[i]在哪个等式中第一次出现,在哪个等式中第二次出现,以及正负号各是什么。
b[i]的出现很显然,i为正,i+1为负
然后求最大费用最大流就可以过了。
/**************************************************************
Problem: 3550
User: Tunix
Language: C++
Result: Accepted
Time:20 ms
Memory:6016 kb
****************************************************************/ //BZOJ 3550
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
#define CC(a,b) memset(a,b,sizeof(a))
using namespace std;
int getint(){
int v=,sign=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') sign=-; ch=getchar();}
while(isdigit(ch)) {v=v*+ch-''; ch=getchar();}
return v*sign;
}
typedef long long LL;
const int N=,M=,INF=~0u>>;
const double eps=1e-;
/*******************template********************/
int n,m,k,a[N],b[N],c[N],w[N];
LL ans;
struct edge{int from,to,v,c;};
struct Net{
edge E[M];
int head[N],next[M],cnt;
void ins(int x,int y,int z,int c){
E[++cnt]=(edge){x,y,z,c};
next[cnt]=head[x]; head[x]=cnt;
}
void add(int x,int y,int z,int c){
ins(x,y,z,c); ins(y,x,,-c);
}
int S,T,d[N],from[N],Q[M];
bool inq[N];
bool spfa(){
int l=,r=-;
F(i,,T)d[i]=INF;
d[S]=; Q[++r]=S; inq[S]=;
while(l<=r){
int x=Q[l++]; inq[x]=;
for(int i=head[x];i;i=next[i])
if(E[i].v && d[x]+E[i].c<d[E[i].to]){
d[E[i].to]=d[x]+E[i].c;
from[E[i].to]=i;
if(!inq[E[i].to]){
Q[++r]=E[i].to;
inq[E[i].to]=;
}
}
}
return d[T]!=INF;
}
void mcf(){
int x=INF;
for(int i=from[T];i;i=from[E[i].from])
x=min(x,E[i].v);
for(int i=from[T];i;i=from[E[i].from]){
E[i].v-=x;
E[i^].v+=x;
}
ans+=x*d[T];
}
void init(){
m=n=getint(); m*=; k=getint(); cnt=;
F(i,,m) a[i]=getint();
S=; T=*n+;
add(S,,k,);
add(n*+,T,k,);
F(i,,n*+) add(i,i+,INF,); F(i,,n+) add(,i,,-a[i-]);
F(i,n+,*n+) add(i,*n+,,-a[i+n-]);
F(i,,n+) add(i,i+n,,-a[i+n-]); while(spfa()) mcf();
printf("%lld\n",-ans);
}
}G1;
int main(){
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
G1.init();
return ;
}
3550: [ONTAK2010]Vacation
Time Limit: 10 Sec  Memory Limit: 96 MB
Submit: 141  Solved: 105
[Submit][Status][Discuss]
Description
有3N个数,你需要选出一些数,首先保证任意长度为N的区间中选出的数的个数<=K个,其次要保证选出的数的个数最大。
Input
第一行两个整数N,K。
第二行有3N个整数。
Output
一行一个整数表示答案。
Sample Input
14 21 9 30 11 8 1 20 29 23 17 27 7 8 35
Sample Output
HINT
【数据范围】
N<=200,K<=10。
Source
【BZOJ】【3550】【ONTAK2010】Vacation的更多相关文章
- 【BZOJ 2754 喵星球上的点名】
		
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2512 Solved: 1092[Submit][Status][Discuss] Descript ...
 - 【BZOJ】3052: [wc2013]糖果公园
		
http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...
 - 【BZOJ】3319: 黑白树
		
http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种: ...
 - 【BZOJ】3319: 黑白树(并查集+特殊的技巧/-树链剖分+线段树)
		
http://www.lydsy.com/JudgeOnline/problem.php?id=3319 以为是模板题就复习了下hld............................. 然后n ...
 - 【BZOJ】【1025】【SCOI2009】游戏
		
DP/整数拆分 整个映射关系可以分解成几个循环(置换群的预备知识?),那么总行数就等于各个循环长度的最小公倍数+1(因为有个第一行的1~N).那么有多少种可能的排数就等于问有多少种可能的最小公倍数. ...
 - 【BZOJ】1013: [JSOI2008]球形空间产生器sphere
		
[BZOJ]1013: [JSOI2008]球形空间产生器sphere 题意:给n+1个n维的点的坐标,要你求出一个到这n+1个点距离相等的点的坐标: 思路:高斯消元即第i个点和第i+1个点处理出一个 ...
 - 【BZOJ】1002:轮状病毒(基尔霍夫矩阵【附公式推导】或打表)
		
Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道.如下图 ...
 - 【BZOJ】【3697】采药人的路径&【3127】【USACO2013 Open】Yin and Yang
		
点分治 Orz hzwer 倒是比较好想到点分治……然而在方案统计这里,我犯了两个错误…… 1.我比较傻逼的想的是:通过儿子来更新父亲,也就是统计以x为根的子树中xxxx的路径有多少条……这样转移. ...
 - 【BZOJ】【3083】遥远的国度
		
树链剖分/dfs序 其实过了[BZOJ][4034][HAOI2015]T2以后就好搞了…… 链修改+子树查询+换根 其实静态树的换根直接树链剖分就可以搞了…… 因为其实只有一样变了:子树 如果roo ...
 - 【BZOJ】【2434】【NOI2011】阿狸的打字机
		
AC自动机+DFS序+BIT 好题啊……orz PoPoQQQ 大爷 一道相似的题目:[BZOJ][3172][TJOI2013]单词 那道题也是在fail树上数有多少个点,只不过这题是在x的fail ...
 
随机推荐
- C#中保留两位小数但不四舍五入的最优做法
			
多种做法比较 class Program_保留两位小数但不四舍五入 { static void Main(string[] args) { Helper.Run(delegate () { metho ...
 - Zookeeper 脑裂
			
转自 http://blog.csdn.net/u010185262/article/details/49910301 Zookeeper zookeeper是一个分布式应用程序的协调服务.它是一个为 ...
 - Linux下的Source命令及脚本的执行方式解析
			
Linux Source命令及脚本的执行方式解析 http://blog.csdn.net/wangyangkobe/article/details/6595143 当我修改了/etc/profile ...
 - 不加班的实践(1)——这真的该用try-catch吗?
			
前言 我有个技能,就是把“我”说的听起来特别像“老子”. 以前是小喽啰的时候,会跟领导说“我!不加班.”,听起来就像“老子不加班!”一样.到最后发现,我确实没有把计划内的工作拖到需要加班才能完成,这个 ...
 - 瀑布流ListView
			
前言 终于忙完了一段时间,现在前段时间写的一个瀑布流ListView到想法分享下,这个东西是扩展自Listview,当列表内容拉到最后后触发刷新操作,以便抓取更多到数据. 先贴下整个代码,先有个整体到 ...
 - 用Python的smtp模块发邮件的示例
			
# -*- coding: UTF-8 -*- import smtplib from email.mime.multipart import MIMEMultipart from email.mim ...
 - WordPress默认栏目设置
			
WordPress是一个注重美学.易用性和网络标准的个人信息发布平台,是全球使用最多的博客系统,只需要在系统后台做一些简单的设计,基本就能实现我们日常个性化发布个人信息的需求,而博客后台的使用其实很简 ...
 - MYSQL查询某字段中以逗号分隔的字符串的方法
			
首先我们建立一张带有逗号分隔的字符串. CREATE TABLE test(id int(6) NOT NULL AUTO_INCREMENT,PRIMARY KEY (id),pname VARCH ...
 - DevExpress控件使用经验总结- GridView列表行号显示操作
			
DevExpress是一个比较有名的界面控件套件,提供了一系列的界面控件套件的DotNet界面控件.本文主要介绍我在使用DevExpress控件过程中,遇到或者发现的一些问题解决方案,或者也可以所示一 ...
 - C#高级功能(四)扩展方法和索引
			
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用.扩展方法被定义为静态方法,但 ...
 
			
		