zoukankan      html  css  js  c++  java
  • 【BZOJ1283/3550】序列/[ONTAK2010]Vacation 最大费用流

    【BZOJ1283】序列

    Description

    给出一个长度为 的正整数序列Ci,求一个子序列,使得原序列中任意长度为 的子串中被选出的元素不超过K(K,M<=100) 个,并且选出的元素之和最大。

    Input

    第1行三个数N,m,k。 接下来N行,每行一个字符串表示Ci。

    Output

    最大和。

    Sample Input

    10 5 3
    4 4 4 6 6 6 6 6 4 4

    Sample Output

    30

    HINT

    20%的数据:n<=10。
    100%的数据:N<=1000,k,m<=100。Ci<=20000。

    题解:很难想的费用流建图,看了题解才略懂,下面说一下建图方法和我的理解:

    1.S->1...i -> i+1...n->T 容量k,费用0
    2.i -> i+m 容量1,费用ai

    我的理解是:假如你只有k个流量,要体现出所有的权值,你该如何利用这k个流量?显然你必须重复利用这些流量,就以[l,l+m]和[l+1,l+m+1],l的流量对l+m+1没有影响,所以l+m+1可以直接将l的流量拿过来用,达到节约流量的目的。这样一来,这k个流量在经过每个区间时都会选择权值最大的路径去走,这样跑最大费用流就能得出正确的解。

    1283

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    int n,m,k,S,T,cnt,ans;
    int to[30000],next[30000],head[1010],cost[30000],flow[30000],dis[1010],inq[1010],pe[1010],pv[1010];
    queue<int> q;
    void add(int a,int b,int c,int d)
    {
    	to[cnt]=b,cost[cnt]=c,flow[cnt]=d,next[cnt]=head[a],head[a]=cnt++;
    	to[cnt]=a,cost[cnt]=-c,flow[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
    }
    int bfs()
    {
    	memset(dis,0x3f,sizeof(dis));
    	dis[S]=0,q.push(S);
    	int i,u;
    	while(!q.empty())
    	{
    		u=q.front(),q.pop(),inq[u]=0;
    		for(i=head[u];i!=-1;i=next[i])
    		{
    			if(dis[to[i]]>dis[u]+cost[i]&&flow[i])
    			{
    				dis[to[i]]=dis[u]+cost[i],pe[to[i]]=i,pv[to[i]]=u;
    				if(!inq[to[i]])	inq[to[i]]=1,q.push(to[i]);
    			}
    		}
    	}
    	return dis[T]<0x3f3f3f3f;
    }
    int main()
    {
    	scanf("%d%d%d",&n,&m,&k);
    	int i,j,a;
    	S=0,T=n+1;
    	memset(head,-1,sizeof(head));
    	add(S,1,0,k);
    	for(i=1;i<=n;i++)
    	{
    		add(i,i+1,0,k);
    		scanf("%d",&a);
    		if(i+m<=n)	add(i,i+m,-a,1);
    		else	add(i,T,-a,1);
    	}
    	while(bfs())
    	{
    		int mf=1<<30;
    		for(i=T;i!=S;i=pv[i])	mf=min(mf,flow[pe[i]]);
    		ans-=dis[T]*mf;
    		for(i=T;i!=S;i=pv[i])	flow[pe[i]]-=mf,flow[pe[i]^1]+=mf;
    	}
    	printf("%d",ans);
    	return 0;
    }
    

    3550

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    int n,k,S,T,cnt,ans;
    int to[30000],next[30000],head[1010],cost[30000],flow[30000],dis[1010],inq[1010],pe[1010],pv[1010];
    queue<int> q;
    void add(int a,int b,int c,int d)
    {
    	to[cnt]=b,cost[cnt]=c,flow[cnt]=d,next[cnt]=head[a],head[a]=cnt++;
    	to[cnt]=a,cost[cnt]=-c,flow[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
    }
    int bfs()
    {
    	memset(dis,0x3f,sizeof(dis));
    	dis[S]=0,q.push(S);
    	int i,u;
    	while(!q.empty())
    	{
    		u=q.front(),q.pop(),inq[u]=0;
    		for(i=head[u];i!=-1;i=next[i])
    		{
    			if(dis[to[i]]>dis[u]+cost[i]&&flow[i])
    			{
    				dis[to[i]]=dis[u]+cost[i],pe[to[i]]=i,pv[to[i]]=u;
    				if(!inq[to[i]])	inq[to[i]]=1,q.push(to[i]);
    			}
    		}
    	}
    	return dis[T]<0x3f3f3f3f;
    }
    int main()
    {
    	scanf("%d%d",&n,&k);
    	int i,j,a;
    	S=0,T=3*n+1;
    	memset(head,-1,sizeof(head));
    	add(S,1,0,k);
    	for(i=1;i<=3*n;i++)
    	{
    		add(i,i+1,0,k);
    		scanf("%d",&a);
    		if(i+n<=3*n)	add(i,i+n,-a,1);
    		else	add(i,T,-a,1);
    	}
    	while(bfs())
    	{
    		int mf=1<<30;
    		for(i=T;i!=S;i=pv[i])	mf=min(mf,flow[pe[i]]);
    		ans-=dis[T]*mf;
    		for(i=T;i!=S;i=pv[i])	flow[pe[i]]-=mf,flow[pe[i]^1]+=mf;
    	}
    	printf("%d",ans);
    	return 0;
    }
  • 相关阅读:
    Socket开发框架之消息的回调处理
    Socket开发框架之数据加密及完整性检查
    Socket开发框架之数据传输协议
    Socket开发框架之框架设计及分析
    C#进行Visio二次开发之文件导出及另存Web页面
    Winform混合式开发框架的特点总结
    代码生成工具Database2Sharp中增加视图的代码生成以及主从表界面生成功能
    基于Metronic的Bootstrap开发框架经验总结(9)--实现Web页面内容的打印预览和保存操作
    基于C#的MongoDB数据库开发应用(4)--Redis的安装及使用
    基于C#的MongoDB数据库开发应用(3)--MongoDB数据库的C#开发之异步接口
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6890419.html
Copyright © 2011-2022 走看看