sdut2414 An interesting game 费用流

建图题


因为每个新添加的小山高度都在(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座大山的的差值输出即可。


  1.  int s=N+31,mid=N+32,t=N+33;  
  2.         g.init(N+34);  
  3.         for(int i=1;i<=N;i++){  
  4.             scanf("%d",&a[i]);  
  5.             if(i>1) ans+=abs(a[i]-a[i-1]);  
  6.         }  
  7.         memset(cnt,0,sizeof(cnt));  
  8.         int tmp;  
  9.         for(int i=1;i<=M;i++){  
  10.             scanf("%d",&tmp);  
  11.             cnt[tmp]++;  
  12.         }  
  13.         g.add_edge(s,mid,K,0);  
  14.         for(int i=0;i<=30;i++) if(cnt[i]){  
  15.             g.add_edge(mid,i,cnt[i],0);  
  16.             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])));  
  17.         }  
  18.         for(int i=2;i<=N;i++) g.add_edge(30+i,t,1,0); 

猜你喜欢

转载自blog.csdn.net/Little_boy_z/article/details/80086027
今日推荐