ZOJ 3362 无向图费用流

本文分享了一次使用MCMF算法解决实际问题的经验,着重讨论了算法应用过程中的常见错误和如何避免。通过实例分析,强调了深入理解题目和算法的重要性,避免模板化思维。同时,提供了代码实现细节,包括SPFA算法优化和MCMF算法的正确使用,旨在帮助读者提高算法理解和应用能力。
今天看了watashi的解题报告后,才发现不是模板错了,是自己对模板不熟,没仔细想题目。导致应该改模板的地方没有改……-_-!

附上代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

const int maxn = 111;
const int maxm = 55555;
const int inf = 1 << 28;
struct node
{
       int  to, next, c, f;
}edge[maxm * 10];

int head[maxn];
int src, des, n, m, k, sm;
int dis[maxn], load[maxn], p[maxn];  // dis is the cost of each node; load is the pre-edge of current edge; p is the pre-node of current node
bool flag[maxn], vis[maxn];
int citi[maxn];

void add_edge(int u, int v, int c, int f)
{
     edge[sm].to = v;
     edge[sm].c = c;
     edge[sm].f = f;
     edge[sm].next = head[u];
     head[u] = sm ++;
     edge[sm].to = u;
     edge[sm].c = 0;
     edge[sm].f = -f;
     edge[sm].next = head[v];
     head[v] = sm ++;
}

bool spfa(int st, int ed)
{
     int que[maxn * 10], qout, qin;
     memset(flag, false, sizeof(flag));
     memset(load, -1, sizeof(load));
     memset(p, -1, sizeof(p));
     for(int i = 0; i <= des + 1; i ++)
             dis[i] = inf;
     qin = qout = 0;
     que[qin ++] = st;
     dis[st] = 0;
     flag[st] = true;
     while(qin != qout)
     {
               int e = que[qout ++];
               flag[e]  =false;
               for(int i = head[e]; i != -1; i = edge[i].next)
               {
                       if(edge[i].c)
                       {
                                    int ne = edge[i].to;
                                    if(dis[ne] - dis[e] > edge[i].f)
                                    {
                                               dis[ne] = edge[i].f + dis[e];
                                               p[ne] = e;
                                               load[ne] = i;
                                               if(!flag[ne])
                                               {
                                                            flag[ne] = true;
                                                            que[qin ++] = ne;
                                               }
                                    }
                       }
               }
     }
     if(dis[ed] == inf)
                return false;
     return true;
}

int MCMF(int st, int ed)
{
    int u, mn;
    int ans_f = 0, ans_c = 0;
    while(spfa(st, ed)) // every time the shortest path is shorter than past edges    {
                   u = ed;
                   mn = inf;
                   if(dis[ed] >= 0)
                              break;
                   while(p[u] != -1)
                   {
                              mn = min(edge[load[u]].c, mn); // find the neck edge
                              u = p[u];
                   }
                   u = ed;
                   while(p[u] != -1)
                   {
                              edge[load[u]].c -= mn;   //every edge minus the capacity of the neck edge
                              edge[load[u]^1].c += mn;  // the opposite edge plus the capacity of the neck edge
                              u = p[u];
                   }
                   ans_c += dis[ed] * mn;
                   ans_f += mn;
    }
    return ans_c;
}

int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
                   int i, j, u, v, c, f;
                   memset(head, -1, sizeof(head));
                   sm = 0;
                   src = 0, des = n + 1;
                   for(i = 2; i <= n; i ++)
                   {
                         scanf("%d", &citi[i]);
                         add_edge(i, des, inf, -citi[i]);
                   }
                   while(m --)
                   {
                           scanf("%d%d%d%d", &u, &v, &c, &f);
                           add_edge(u, v, c, f);
                           add_edge(v, u, c, f);
                   }

                   add_edge(src, 1, inf, 0);
                   int ans = MCMF(src, des);
                   printf("%d\n", -ans);
    }
}


 

最重要的是MCMF里的这个地方:

                   if(dis[ed] >= 0)
                              break;

意思是:每次做完最短路,如果值大于等于0,那么就break掉,因为>=0的意思就是亏本生意,这个肯定是要判定否决掉的。怪不得一开始没改的时候,样例出来的值始终比output要小100……还是题目没想明白的原因。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值