建图题
因为每个新添加的小山高度都在(0-30)之间,所以我们以这31个点,也就是高度作为点
S-》S’容量为k,用来表明最多添加k个
S'指向31个小山,容量为每个高度小山的个数。
31个小山在指向n个大山。容量为1,费用比较麻烦。原本没有这个小山时,
我们是abs(a[j]-a[j-1])。我们计算的是多余的,所以要把这一块减去,再加上加上小山后的值。
也就是-(abs(i-a[j])+abs(i-a[j-1])-abs(a[j]-a[j-1]))。
之后n个大山在指向终点,流量为1,每个大山只能添加一个小山。
注意建图见负数,用来求最小值。之后加上最初n座大山的的差值输出即可。
- int s=N+31,mid=N+32,t=N+33;
- g.init(N+34);
- for(int i=1;i<=N;i++){
- scanf("%d",&a[i]);
- if(i>1) ans+=abs(a[i]-a[i-1]);
- }
- memset(cnt,0,sizeof(cnt));
- int tmp;
- for(int i=1;i<=M;i++){
- scanf("%d",&tmp);
- cnt[tmp]++;
- }
- g.add_edge(s,mid,K,0);
- for(int i=0;i<=30;i++) if(cnt[i]){
- g.add_edge(mid,i,cnt[i],0);
- for(int j=2;j<=N;j++) g.add_edge(i,30+j,1,-(abs(i-a[j])+abs(i-a[j-1])-abs(a[j]-a[j-1])));
- }
- for(int i=2;i<=N;i++) g.add_edge(30+i,t,1,0);