BZOJ1283 序列

来源:互联网 发布:漫步者煲机软件 编辑:程序博客网 时间:2024/06/04 23:36

这个算是经典建模裸题了吧?然而还是没秒掉

使得每个长度为m的子串中选不超过k个,可以视为选k个子序列,每次选的时候相邻两个的位置差>m

那么每个点连后一个点费用0流量INF,连往后数m个点(如果超数组长度了就连T)费用a[i]流量1,S连1号点流量k费用0,跑最大费用流即可

#include<iostream>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<cstdlib>#include<cstdio>#include<map>#include<bitset>#include<set>#include<stack>#include<vector>#include<queue>using namespace std;#define MAXN 1010#define MAXM 10010#define ll long long#define eps 1e-8#define MOD 1000000007#define INF 1000000000struct vec{int to;int fro;int f;int v;};vec mp[MAXM];int tai[MAXN],cnt=1;int answ;int s,t;int dis[MAXN];int rd[MAXN];int q[MAXN],hd,tl;bool iq[MAXN];inline void be(int x,int y,int f,int v){mp[++cnt].to=y;mp[cnt].fro=tai[x];tai[x]=cnt;mp[cnt].f=f;mp[cnt].v=v;}inline void bse(int x,int y,int f,int v){be(x,y,f,v);be(y,x,0,-v);}bool spfa(){int i,x,y;memset(dis,0xef,sizeof(dis));dis[s]=0;hd=tl=0;iq[q[tl++]=s]=1;while(hd!=tl){iq[x=q[(hd%=MAXN)++]]=0;for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;if(dis[y]<dis[x]+mp[i].v&&mp[i].f){dis[y]=dis[x]+mp[i].v;rd[y]=i;if(!iq[y]){iq[q[(tl%=MAXN)++]=y]=1;}}}}if(dis[t]<0){return 0;}int flow=INF;for(i=t;i!=s;i=mp[rd[i]^1].to){flow=min(flow,mp[rd[i]].f);}answ+=flow*dis[t];for(i=t;i!=s;i=mp[rd[i]^1].to){mp[rd[i]].f-=flow;mp[rd[i]^1].f+=flow;}return 1;}int n,m,k;int main(){int i,x;scanf("%d%d%d",&n,&m,&k);for(i=1;i<=n;i++){scanf("%d",&x);bse(i,min(n+1,i+m),1,x);bse(i,i+1,INF,0);}s=n+2;t=n+1;bse(s,1,k,0);while(spfa()){}printf("%d\n",answ);return 0;}/**/


原创粉丝点击