【XSY2689】王子 - 网络流

复活!qwq

题目来源:2018冬令营模拟测试赛(九)

题意:

【背景描述】

    不是所有王子都会遇见自己的中关村,主公,公主。

    从前有个王子姓王,王王子遇到了一位美丽的公主,她的名字当然是公公主啦。

    王王子对公公主一见钟情,他想方设法地去讨好公公主, 他准备了N个节目依次表演给公主看,每个节目他可以倒立表演,或者正常表演。王王子非常聪明,所以他总是能预估出每个节目的每种表演形式能刷多少好感度,我们记第i个节目倒立表演能增加Ai的好感度,正常表演能增加Bi的好感度。

    这个公公主也不是一个省油的灯,他(没打错)看节目的时候既不喜欢太循规蹈矩,也不喜欢太标新立异。准确的说,他看的王子表演的任意连续K个节目里面,至少有P个倒立表演的节目,Q个正常表演的节目。

    王王子想知道,在满足公公主的特殊癖好的前提下,他最多能刷多少的好感度。

【输入数据】

第一行四个整数N,K,P,Q。

接下来N行每行两个整数表示Ai和Bi。

【输出数据】

一行一个正整数表示答案。

【数据规模】

对于 20% 的数据,N < 16。

对于另外 30% 的数据, K < 10。

对于另外 30% 的数据, Ai, Bi < 4

对于 100% 的数据, 0 < N < 200, 0 < Ai, Bi < 10000000, 0 ≤ P + Q ≤ K ≤ N。

题解:

这种鬼畜题面和数据范围肯定就是网络流啦~

题目中一共有$N-K+1$个限制区间,显然一个节目倒立表演的话所有包含它的区间倒立表演的机会都少了一个;

那么可以把每个区间看成一个点,一个流量就表示一次倒立表演的机会,那么一个节目就会对应从最前的一个包含它的区间到最前的一个不包含它的区间的一条边,表示如果倒立表演,这些区间的机会都会减少一个(流量流掉了);

限制倒立的节目最多有多少个就相当于限制总流量,直接限制每个点到下一个点的边的流量即可;

加上最优的限制条件可以考虑先全选$A_i$,然后把费用设成$A_i-B_i$;

然后就是费用流随便跑了。

代码:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 #define eps 1e-9
 9 using namespace std;
10 typedef long long ll;
11 struct edge{
12     int v,w,z,next;
13 }a[100001];
14 int n,k,p,q,ans=0,N,vs,vt,tot=1,head[50001],sp[50001],fr[50001],s1[201],s2[201];
15 bool isin[50001];
16 void add(int u,int v,int w,int z){
17     a[++tot].v=v;
18     a[tot].w=w;
19     a[tot].z=z;
20     a[tot].next=head[u];
21     head[u]=tot;
22     a[++tot].v=u;
23     a[tot].w=0;
24     a[tot].z=-z;
25     a[tot].next=head[v];
26     head[v]=tot;
27 }
28 bool spfa(){
29     int flw,mi=inf;
30     queue<int>q;
31     memset(isin,0,sizeof(isin));
32     for(int i=0;i<=N;i++)sp[i]=-inf;
33     q.push(vs);
34     isin[vs]=true;
35     sp[vs]=0;
36     while(!q.empty()){
37         int u=q.front();
38         q.pop();
39         isin[u]=false;
40         for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
41             int v=a[tmp].v;
42             if(sp[v]<sp[u]+a[tmp].z&&a[tmp].w){
43                 fr[v]=tmp;
44                 sp[v]=sp[u]+a[tmp].z;
45                 if(!isin[v]){
46                     q.push(v);
47                     isin[v]=true;
48                 }
49             }
50         }
51     }
52     if(sp[vt]==-inf)return false;
53     for(int i=vt;i!=vs;i=a[fr[i]^1].v){
54         mi=min(mi,a[fr[i]].w);
55     }
56     for(int i=vt;i!=vs;i=a[fr[i]^1].v){
57         ans+=mi*a[fr[i]].z;
58         a[fr[i]].w-=mi;
59         a[fr[i]^1].w+=mi;
60     }
61     return true;
62 }
63 int main(){
64     memset(head,-1,sizeof(head));
65     scanf("%d%d%d%d",&n,&k,&p,&q);
66     for(int i=1;i<=n;i++){
67         scanf("%d%d",&s1[i],&s2[i]);
68         ans+=s2[i];
69     }
70     vs=0;
71     vt=n+1;
72     N=n+2;
73     add(vs,N,k-q,0);
74     for(int i=1;i<=k;i++){
75         add(N,i,1,0);
76     }
77     for(int i=1;i<=n;i++){
78         add(i,i+1,k-q-p,0);
79         if(i+k<=n)add(i,i+k,1,s1[i]-s2[i]);
80         else add(i,vt,1,s1[i]-s2[i]);
81     }
82     while(spfa());
83     printf("%d",ans);
84     return 0;
85 }
posted @ 2018-11-27 08:08  DCDCBigBig  阅读(257)  评论(0编辑  收藏  举报