JZOJ 5378. 【NOIP2017提高A组模拟9.19】闷声刷大题(60分)
来源:互联网 发布:完美root软件 编辑:程序博客网 时间:2024/06/08 15:12
题目
60分题解
最小费用流!!!!!
看到选k个a[i],b[i],并且选的每个b的下标不小于对应的a的下标。
考虑最小费用流!!!!!
将每一天拆成两个点(A部分和B部分)。
S向每个点的A部分连边(费用为a[i],容量为1)。每个点的A向B连一条边(费用为0,容量为1)。
这样就可以表达选的A的下标小于等于对应的B的下标的意思。
首先,普通的SPFA求费用流,只有40分。
然而,ZKW费用流,60分,但我不会打。
怎么从40优化到60?
①在spfa中加一个STL优化(因为这个SPFA是求最短路的)即最新加入队列中的元素比目前队头更优,就先让最新加入队列中的元素出队。
②加入读入优化。(这个显然可以优化一点点时间)
③能把long long写成int的变量就写成int,这样子也会快很多。
代码
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 300010#define LL long long#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)#define eg(i,x) for(i=head[x];i;i=edge[i].next)using namespace std;struct note{ int to,next; LL flow,val;};note edge[N*10];LL head[N],tot,ans;LL S,T,a[N],b[N];LL dis[N];int pre[N],qu[N*10];bool bz[N],p;LL i,j,k,l,n,m;LL read(){ LL fh=1,res=0;char ch; while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if (ch=='-')fh=-1,ch=getchar(); while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar(); return res*fh;}void lb(int x,int y,LL z,LL w){ edge[++tot].to=y;edge[tot].next=head[x];edge[tot].flow=z;edge[tot].val=w;head[x]=tot; edge[++tot].to=x;edge[tot].next=head[y];edge[tot].flow=0;edge[tot].val=-w;head[y]=tot;}bool spfa(){ memset(dis,127,sizeof(dis));dis[S]=0; memset(bz,0,sizeof(bz)); memset(pre,0,sizeof(pre)); int t=0,w=1,i,now; qu[1]=S; while(t<w){ now=qu[++t]; eg(i,now){ if (edge[i].flow>0 && dis[edge[i].to]>dis[now]+edge[i].val){ dis[edge[i].to]=dis[now]+edge[i].val; pre[edge[i].to]=i; if(!bz[edge[i].to]){ bz[edge[i].to]=1; qu[++w]=edge[i].to; if (dis[qu[w]]<dis[qu[t+1]])swap(qu[t+1],qu[w]); } } } bz[now]=0; } if (dis[T]!=9187201950435737471) return 1;else return 0;}void find(){ LL x=T,sum=0,mx=9187201950435737471; while (x!=S){ mx=min(mx,edge[pre[x]].flow); x=edge[pre[x]^1].to; } x=T; while (x!=S){ edge[pre[x]].flow-=mx; edge[pre[x]^1].flow+=mx; sum+=edge[pre[x]].val; x=edge[pre[x]^1].to; } ans+=sum*mx;}bool cmp(LL x,LL y){return x<y;}int main(){ freopen("orz.in","r",stdin); freopen("orz.out","w",stdout); n=read();k=read(); fo(i,1,n)a[i]=read(); fo(i,1,n)b[i]=read(); p=0; fo(i,2,n)if(a[i]!=a[i-1]){ p=1; break; } if(!p){ ans=0; sort(b+1,b+n+1,cmp); fo(i,1,k) ans+=b[i]+a[i]; printf("%lld",ans); return 0; } tot=1;S=0,T=2*n+2; fo(i,1,n){ lb(S,i,1,a[i]); lb(i,i+n,1,0); if (i<n) lb(i+n,i+n+1,9187201950435737471,0); lb(i+n,1+n*2,1,b[i]); } lb(n*2+1,T,k,0); ans=0; while (spfa())find(); printf("%lld",ans); return 0;}
阅读全文
2 0
- JZOJ 5378. 【NOIP2017提高A组模拟9.19】闷声刷大题(60分)
- 【JZOJ 5377】【NOIP2017提高A组模拟9.19】开拓
- JZOJ 5376. 【NOIP2017提高A组模拟9.19】Candy
- JZOJ 5377. 【NOIP2017提高A组模拟9.19】开拓
- 【JZOJ 4931】【NOIP2017提高组模拟12.24】A
- 【JZOJ 4931】【NOIP2017提高组模拟12.24】A
- JZOJ 5195. 【NOIP2017提高组模拟7.3】A
- JZOJ 100026. 【NOIP2017提高A组模拟7.7】图
- JZOJ 100030. 【NOIP2017提高A组模拟7.8】为了爱情
- jzoj. 100031. 【NOIP2017提高A组模拟7.9】外星密码
- JZOJ 100035【NOIP2017提高A组模拟7.10】区间
- JZOJ 100036 【NOIP2017提高A组模拟7.10】随机
- JZOJ 100037【NOIP2017提高A组模拟7.11】后缀数组
- JZOJ 100035. 【NOIP2017提高A组模拟7.10】区间
- JZOJ 100041. 【NOIP2017提高A组模拟7.12】列车调度
- JZOJ 100045. 【NOIP2017提高A组模拟7.13】好数
- JZOJ 100046. 【NOIP2017提高A组模拟7.14】收集卡片
- JZOJ 100047. 【NOIP2017提高A组模拟7.14】基因变异
- js 函数调用其他函数和方法 call,apply关键字
- git 操作笔记
- (二)用 svm 识别手写体数字图片
- I2C设备驱动
- Android Studio Gradle
- JZOJ 5378. 【NOIP2017提高A组模拟9.19】闷声刷大题(60分)
- 前端~腾讯课堂选项卡部分代码
- maven(ssm)
- 算法学习之动态规划--最长公共子序列
- hdu 1251 统计难题
- AndroidStudio的文件的结构,so文件配置
- opencv3.1.0+contrib模块编译总结
- linux添加开机自启动脚本示例详解
- day3——利用python创立ORM