SPOJ BOXES

来源:互联网 发布:淘宝起什么名字好 编辑:程序博客网 时间:2024/04/28 09:51

There are n boxes on the circle. The boxes are numbered from 1 to n
(1<=n<=1000) in clock wise order. There are balls in the boxes, and
the number of all the balls in the boxes is not greater than n.

The balls should be displaced in such a way that in each box there
remains no more than one ball. In one move we can shift a ball from
one box to one of it’s neighboring boxes.

Write a program that: reads from the standard input the number of
boxes n and the arrangement of balls in the boxes, computes the
minimal number of moves necessary to displace the balls in such a way
that in each box there remains no more than one ball, writes the
result in the standard output. Input

The first line of the input file contains an integer t representing
the number of test cases (t<=20). Then t test cases follows. Each test
case has the following form:

The first line contains one positive integer n - the number of boxesThe second line contains n nonnegative integer separated by single spaces. The i-th number is the number of balls in the i-th box. 

Output

For each test case, output one nonnegative integer - the number of
moves necessary to displace the balls in such a way that in each box
there remains no more than one ball.

费用流。
如果一个位置u没有石子,它可以解决另外一个石子,连边(u,t,1,0)。如果一个位置u的石子数au多于一个,他需要别的位置解决他。连边(s,u,au1,0)。相互之间解决是有代价的,对相邻的u,v连边(u,v,oo,1)

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int s=1005,t=1006,oo=0x3f3f3f3f;int fir[1010],ne[20010],to[20010],w[20010],c[20010],in[1010],que[1010],len[1010],minw[1010],fa[1010],n,num;void add(int u,int v,int x,int y){    num++;    ne[num*2]=fir[u];    fir[u]=num*2;    to[num*2]=v;    w[num*2]=x;    c[num*2]=y;    ne[num*2+1]=fir[v];    fir[v]=num*2+1;    to[num*2+1]=u;    w[num*2+1]=0;    c[num*2+1]=-y;}void init(){    int x;    scanf("%d",&n);    num=0;    memset(fir,0,sizeof(fir));    for (int i=0;i<n;i++)    {        scanf("%d",&x);        if (!x) add(i,t,1,0);        if (x>1) add(s,i,x-1,0);        add(i,(i+1)%n,oo,1);        add(i,(i-1+n)%n,oo,1);    }}void check(){    for (int i=0;i<=t;i++)        for (int j=fir[i];j;j=ne[j])            if (w[j]) printf("%d->%d:%d,%d\n",i,to[j],w[j],c[j]);}bool spfa(){    /*check();    printf("\n\n\n");*/    int hd=0,tl=1,u,v,mod=n+5;    que[0]=s;    in[s]=1;    memset(len,0x3f,sizeof(len));    len[s]=0;    memset(minw,0,sizeof(minw));    minw[s]=oo;    while (hd!=tl)    {        u=que[hd++];        hd%=mod;        for (int i=fir[u];i;i=ne[i])            if (len[u]+c[i]<len[v=to[i]]&&w[i])            {                len[v]=len[u]+c[i];                fa[v]=i;                minw[v]=min(minw[u],w[i]);                if (!in[v])                {                    in[v]=1;                    que[tl++]=v;                    tl%=mod;                }            }        in[u]=0;    }    return minw[t];}int find(){    for (int i=fa[t];i;i=fa[to[i^1]])    {        w[i]-=minw[t];        w[i^1]+=minw[t];    }    return minw[t]*len[t];}int main(){    int T,ans;    scanf("%d",&T);    while (T--)    {        init();        //check();        ans=0;        while (spfa()) ans+=find();        printf("%d\n",ans);    }}
0 0
原创粉丝点击