hdoj 2282 Chocolate 【最小费用最大流】



Chocolate

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 565    Accepted Submission(s): 281


Problem Description
Lethe loves eating chocolates very much. In Lethe's birthday, her good friend echo brings N boxes to her, and makes the boxes on the circle. Furthermore, echo tells Lethe that there are many chocolates in the boxes, but the total number of chocolates doesn't exceed N. Also, echo wants Lethe to displace the chocolates in such a way that in each box remains no more than one chocolate. In one move she can shift one chocolate from current box to its neighboring box. (Each box has two neighboring boxes). Can you tell Lethe the minimum number of move to achieve this goal?
 

Input
There are multi-cases (The total number of cases won't exceed 20). First line is an integer N(1<=N<=500), the total number of boxes. Then N lines follow, each line includes a number, indicates the number of chocolates in the box.
 

Output
Output the minimum number of move.
 

Sample Input
       
       
       
       
10 1 3 3 0 0 2 0 0 0 0
 

Sample Output
       
       
       
       
9
 


晕了,中午看个题,在最大流和费用流之间纠结很长时间,表示代码一直在换。。。最后终于确定是费用流,但想了足足1个多小时建不出来图,醉了。

上网看大牛题解——神马限流限容,还要根据整除关系分类建边来保证费用的最大效率。。。各种神级思维,大脑有点吃不消。 赶紧换题做,这道留着明天KO掉。  


题意:有N个围成一圈的盒子(盒子1和盒子N相接),初始每个盒子都会有一定数量的巧克力。已知一个盒子可以和它相邻的两个盒子交换巧克力,每交换一次算一次操作。问你最少需要多少次操作能够使得每个盒子里面最多只有一个巧克力。


这道题没有问能否成功。若问的话,只需要记录流入汇点的最小可行流和最大可行流,判断最后跑出的最大流在不在这个范围之内就行了。费用流和KM都可以写,抽空来补KM算法。 


简单题,思路不具体说了。说下建图

建图:设置超级源点source,超级汇点sink

1,source向每个盒子建边,容量为盒子所拥有的巧克力数目,费用为0;

2,每个盒子向sink建边,容量为1,表示每个盒子不能超过1个巧克力,费用为0;

3,每个盒子向相邻的盒子建边,容量为无穷大,表示可以无限转移,费用为1。

最后跑一次费用流就行了。


AC代码:


#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define MAXN 600
#define MAXM 10000
#define INF 0x3f3f3f3f
using namespace std;
struct Edge
{
    int from, to, cap, flow, cost, next;
};
Edge edge[MAXM];
int head[MAXN], edgenum;
int dist[MAXN], pre[MAXN];
bool vis[MAXN];
int N;
int source, sink;
void init()
{
    edgenum = 0;
    memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, int w, int c)
{
    Edge E1 = {u, v, w, 0, c, head[u]};
    edge[edgenum] = E1;
    head[u] = edgenum++;
    Edge E2 = {v, u, 0, 0, -c, head[v]};
    edge[edgenum] = E2;
    head[v] = edgenum++;
}
void getMap()
{
    source = 0, sink = N+1;
    int a;
    for(int i = 1; i <= N; i++)
    {
        scanf("%d", &a);
        addEdge(source, i, a, 0);
        addEdge(i, sink, 1, 0);
        if(i == 1)//1和N的时候要注意
        {
            addEdge(1, N, INF, 1);
            addEdge(1, 2, INF, 1);
        }
        else if(i == N)
        {
            addEdge(N, N-1, INF, 1);
            addEdge(N, 1, INF, 1);
        }
        else
        {
            addEdge(i, i-1, INF, 1);
            addEdge(i, i+1, INF, 1);
        }
    }
}
bool SPFA(int s, int t)
{
    queue<int> Q;
    memset(dist, INF, sizeof(dist));
    memset(vis, false, sizeof(vis));
    memset(pre, -1, sizeof(pre));
    dist[s] = 0;
    vis[s] = true;
    Q.push(s);
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        vis[u] = false;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            Edge E = edge[i];
            if(dist[E.to] > dist[u] + E.cost && E.cap > E.flow)
            {
                dist[E.to] = dist[u] + E.cost;
                pre[E.to] = i;
                if(!vis[E.to])
                {
                    vis[E.to] = true;
                    Q.push(E.to);
                }
            }
        }
    }
    return pre[t] != -1;
}
void MCMF(int s, int t, int &cost)
{
    cost = 0;
    while(SPFA(s, t))
    {

        int Min = INF;
        for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
        {
            Edge E = edge[i];
            Min = min(Min, E.cap-E.flow);
        }
        for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
        {
            edge[i].flow += Min;
            edge[i^1].flow -= Min;
            cost += edge[i].cost * Min;
        }
    }
}
int main()
{
    while(scanf("%d", &N) != EOF)
    {
        init();
        getMap();
        int cost;
        MCMF(source, sink, cost);
        printf("%d\n", cost);
    }
    return 0;
}



你可能感兴趣的:(hdoj 2282 Chocolate 【最小费用最大流】)