zoukankan      html  css  js  c++  java
  • SPOJ BOXES

    给出n个循环位置,每个位置有一定数量的盒子,每次操作可以使一个盒子转移到相邻位置,问最少需要转移多少次使得所有位置上的盒子的数量不会超过1个。

    简单题。对于每个位置,加边(s,i,a[i],0),(i,t,1,0)。对于相邻的位置加边(i,i+1,inf,1),(i,i-1,inf,1) 。

    显然最后我们需要求的就是最小费用了。

    召唤代码君:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define maxn 1010
    #define maxm 55555
    using namespace std;
    
    const int inf=maxn;
    int to[maxm],cap[maxm],cost[maxm],next[maxm],first[maxn],edge;
    int d[maxn],num[maxn],from[maxn],tag[maxn],TAG=222;
    int Q[maxm],bot,top;
    int n,m,s,t,ans,T,a[maxn];
    
    void _init()
    {
        edge=-1,s=0,t=n+1,ans=0;
        for (int i=s; i<=t; i++) first[i]=-1;
    }
    
    void addedge(int U,int V,int W,int C)
    {
        edge++;
        to[edge]=V,cap[edge]=W,cost[edge]=C,next[edge]=first[U],first[U]=edge;
        edge++;
        to[edge]=U,cap[edge]=0,cost[edge]=-C,next[edge]=first[V],first[V]=edge;
    }
    
    bool bfs()
    {
        Q[bot=top=1]=s,d[s]=0,num[s]=inf,from[s]=-1,tag[s]=++TAG;
        while (bot<=top){
            int cur=Q[bot++];
            for (int i=first[cur]; i!=-1; i=next[i])
                if (cap[i]>0 && (tag[to[i]]!=TAG || d[cur]+cost[i]<d[to[i]])){
                    d[to[i]]=d[cur]+cost[i];
                    tag[to[i]]=TAG,
                    num[to[i]]=min(num[cur],cap[i]);
                    Q[++top]=to[i];
                    from[to[i]]=i;
                }
        }
        if (tag[t]!=TAG || num[t]<=0) return false;
        ans+=num[t]*d[t];
        for (int i=t; from[i]!=-1; i=to[from[i]^1])
            cap[from[i]]-=num[t],cap[from[i]^1]+=num[t];
        return true;
    }
    
    int main()
    {
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d",&n);
            _init();
            for (int i=1; i<=n; i++) {
                scanf("%d",&a[i]);
                addedge(s,i,a[i],0);
                addedge(i,t,1,0);
                if (i<n) addedge(i,i+1,inf,1);
                if (i>1) addedge(i,i-1,inf,1);
            }
            addedge(1,n,inf,1);
            addedge(n,1,inf,1);
            while (bfs()) ;
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    第15周作业
    软件工程结课作业
    第13次作业--邮箱的正则表达式
    第12次作业
    第10次作业
    Java 8 新的时间日期库
    你还在用if-else吗?
    Java并发编程:4种线程池和缓冲队列BlockingQueue
    ZooKeeper学习第八期——ZooKeeper伸缩性(转)
    ZooKeeper学习第七期--ZooKeeper一致性原理(转)
  • 原文地址:https://www.cnblogs.com/lochan/p/3872421.html
Copyright © 2011-2022 走看看