今天看了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……还是题目没想明白的原因。
本文分享了一次使用MCMF算法解决实际问题的经验,着重讨论了算法应用过程中的常见错误和如何避免。通过实例分析,强调了深入理解题目和算法的重要性,避免模板化思维。同时,提供了代码实现细节,包括SPFA算法优化和MCMF算法的正确使用,旨在帮助读者提高算法理解和应用能力。

363

被折叠的 条评论
为什么被折叠?



