费用流+线性规划

搞了很长时间。。。

我们可以设立式子,a[1]+a[2]+a[3]+...+a[n]<=k , ... , a[2 * n + 1]+ ... +a[3*n]<=k

a是指该位有没有选

那么我们添加一个辅助变量f

a[1]+a[2]+a[3]+...+a[n]+f[1]=k,

...

a[2*n+1]+...+a[3*n]+f[2*n+1]=k

我们就得到了2n+1个式子

然后我们添加两个式子a(0):0=0 a(2*n+2):0=0

然后差分得到2n+2个式子,后一个式子减前一个式子

0:a[1]+a[2]+...+a[n]+f[1]=k

1:a[2]+...+a[n+1]+f[2]-a[1]-...-a[n]-f[1]=0->a[n+1]+f[2]-a[1]-f[1]=0

2:a[n+2]+f[3]-a[2]-f[2]=0

...

2n+1:a[3*n]+f[2*n+1]-a[2*n]-f[2*n]

2n+2:a[2n+1]+...+a[3*n]+f[2*n+1]=k

然后这个式子很像网络流的流量平衡,于是这样建图,正对负,负对正,因为第0项是a[1]+...+a[n],所以0->[1,n],因为都是这样形式的a[n+1]+f[2]-a[1]-f[1],-a[1]和+a[1]对应,因为a∈[0,1],所以流量为1,a[i]=1是指选了a[i],所以费用为a[i]

i-1->i,因为相邻两项-f[i],+f[i],f[i]∈[0,k],因为是辅助变量,所以什么都没有对应,流量为k,费用为0

后面类似 然后就建好图了 设立源汇和1n相连,流量为k 感觉理解不够深刻 碰见这种序列+限制的题可以用费用流做,先把限制代数化,然后-+连边,一般还会相邻的点之间连边,这样可以解决一些序列的问题,以后碰见再做

#include<bits/stdc++.h>
using namespace std;
const int N = , inf = 0x3f3f3f3f;
struct edge {
int nxt, to, f, c;
} e[N * ];
int n, m, k, source, sink, tot, cnt = , sum;
int a[N], head[N], d[N], pree[N], prev[N], vis[N], live[N], dead[N], day[N], c[N], l[N], p[N];
inline void link(int u, int v, int f, int c)
{
e[++cnt].nxt = head[u];
head[u] = cnt;
e[cnt].f = f;
e[cnt].to = v;
e[cnt].c = c;
}
inline void insert(int u, int v, int f, int c)
{
link(u, v, f, c);
link(v, u, , -c);
}
bool spfa()
{
memset(d, -, sizeof(d));
d[source] = ;
queue<int> q;
q.push(source);
while(!q.empty())
{
int u = q.front();
q.pop();
vis[u] = ;
for(int i = head[u]; i; i = e[i].nxt) if(e[i].f && (d[e[i].to] < d[u] + e[i].c || d[e[i].to] == -))
{
pree[e[i].to] = i;
prev[e[i].to] = u;
d[e[i].to] = d[u] + e[i].c;
if(vis[e[i].to] == )
{
q.push(e[i].to);
vis[e[i].to] = ;
}
}
}
return d[sink] != -;
}
inline int Edmonds_Karp()
{
int ans = ;
while(spfa())
{
int now = sink, delta = inf;
while(now != source)
{
delta = min(delta, e[pree[now]].f);
now = prev[now];
}
now = sink;
while(now != source)
{
e[pree[now]].f -= delta;
e[pree[now] ^ ].f += delta;
now = prev[now];
}
ans += delta * d[sink];
}
return ans;
}
int main()
{
scanf("%d%d", &n, &k);
for(int i = ; i <= * n; ++i) scanf("%d", &a[i]);
source = * n + ;
sink = * n + ;
int s = , t = * n + ;
insert(source, s, k, );
insert(t, sink, k, );
sink = * n + ;
for(int i = ; i <= n; ++i) insert(s, i, , a[i]);
for(int i = ; i <= * n + ; ++i) insert(i - , i, k, );
for(int i = n + ; i <= * n; ++i) insert(i, t, , a[i + n]);
for(int i = n + ; i <= * n; ++i) insert(i - n, i, , a[i]); /* for(int i = 1; i <= 2 * n + 1; ++i) insert(i - 1, i, k, 0);
for(int i = 1; i <= n; ++i)
{
insert(s, i, 1, a[i]);
insert(i, i + n, 1, a[i + n]);
insert(i + n, t, 1, a[i + 2 * n]);
} */
printf("%d\n", Edmonds_Karp());
return ;
}

最新文章

  1. Oracle 中 union 和union all 的简单使用说明
  2. SharePoint 2013 托管导航及相关配置
  3. angular.bind() 函数
  4. Codeforces Round 261 Div.2 D Pashmak and Parmida&#39;s problem --树状数组
  5. HTML-Canvas02
  6. 让你的linux操作系统更加安全【转】
  7. 权威第三方报告——获取IT产品竞争力信息的主要途径,类似你买电脑前上的xx论坛看实力评估
  8. 使用Spring的Property文件存储测试数据 - 编写测试和调用测试数据
  9. java下properties属性文件操作
  10. error LNK2019: 无法解析的外部符号 &quot;public:
  11. hdu 4975 最大流问题解决队伍和矩阵,利用矩阵dp优化
  12. Java面向对象 线程技术 -- 下篇
  13. 使用wget做站点镜像及wget的高级用法
  14. 路由刷rom手册
  15. spring4笔记----spring4构造注入
  16. 资源推荐:特意挑选了11个可以称得上“神器”的Windows工具下载
  17. ux.form.field.Password 密码与非密码状态切换
  18. 【剑指offer】逆序输出链表
  19. 关于USBHID协议以及鼠标键盘描述符的解释【转】
  20. 22 Best Sites To Download Free Sprites

热门文章

  1. 洛谷——P3811 【模板】乘法逆元
  2. HDU - 5952 Counting Cliques(dfs搜索)
  3. 每日命令:(3)pwd
  4. Struts2的介绍
  5. C语言之自定义__DATE__与__TIME__
  6. BZOJ 4094 USACO 2013 Dec. Optimal Milking
  7. JS权威指南笔记1
  8. 如何通过js在子页面调用父页面元素的click事件
  9. Portal嵌入SAPUI5应用程序
  10. Ubuntu 16.04安装Bless十六进制编辑器