没事可以骗分
费用流,顾名思义,就是有费用的流,也就是说,给一个网络流图中的每条弧增加一个单位流量费用。
一般来说求解的费用流都是最大流最小费用。
好像没什么好BB的
这里推荐使用zkw算法求解最小费用流,看着代码理解就行,应该还是很好理解的。
(zkw算法在稠密图上跑得飞快,在稀疏图上还不如直接SPFA)
#include <bits/stdc++.h>
using namespace std;
const int max_l = 1000005;
const int maxdelta = 2e9;
struct hazaking
{
int y, next, v, c;
}e[max_l];//c表示这条边的单位流量费用
int linkk[max_l];
int t = 1;
int dis[max_l], delta[max_l], q[max_l*10], p[max_l];
bool vis[max_l];
long long ans = 0;
inline void insert(int x,int y,int z,int c)
{
e[++t].next = linkk[x];
e[t].y = y;
e[t].v = z;
e[t].c = c;
linkk[x] = t;
e[++t].next = linkk[y];
e[t].y = x;
e[t].v = 0;
e[t].c = -c;//反向边为负费用
linkk[y] = t;
}
inline int read()
{
int sum = 0, flag = 1;
char c = getchar();
for (; c < '0' || c > '9' ; c = getchar())
if (c == '-') flag = -1;
for (; c >= '0' && c <= '9'; c = getchar())
sum = (sum << 3) + (sum << 1) + c - 48;
return sum * flag;
}
int n = read(), m = read();
inline bool spfa()
{
memset(vis, false, sizeof(vis));
for (int i = 1; i < n; i++)
dis[i] = int (2e9);//初始化dis数组
dis[n] = 0;
vis[n] = true;
q[1] = n;//这里的SPFA是需要倒着跑的
int qh = 1, qt = 1;
while (qh <= qt)
{
for (int i = linkk[q[qh]]; i ; i = e[i].next )
if (e[i^1].v && dis[e[i].y] > dis[q[qh]] - e[i].c )//由于是倒着跑,需要修改一下if
{
dis[e[i].y] = dis[q[qh]] - e[i].c;//修改dis
if (!vis[e[i].y])
{
vis[e[i].y] = true;
q[++qt] = e[i].y;//入队
}
}
vis[ q[qh++] ] = false;
}
return dis[1] != int (2e9);
}
int dfs(int k,int delta)
{
vis[k] = true;
if (k == n) return delta;
int ma = 0, add;
for (int i = linkk[k]; i && ma < delta; i = e[i].next)
if (!vis[e[i].y] && e[i].v && dis[e[i].y] == dis[k] - e[i].c)
{
if (add = dfs(e[i].y, min(e[i].v, delta - ma)))
{
ans += add * e[i].c;//给最小费用加上费用,由于c是单位流量费用,这里要乘起来
e[i].v -= add;
e[i ^ 1].v += add;
ma += add;
}
}
return ma;
}
inline int costflow()
{
int ans=0;
while (spfa())
{
vis[n] = true;
while (vis[n])
{
memset(vis, false, sizeof(vis));
ans+=dfs(1, maxdelta);
}
}
return ans;
}
inline void init()
{
for (int i = 1; i <= m; i++)
{
int x = read(), y = read(), z = read(), c = read();
insert(x, y, z, c);
}
}
inline void work()
{
printf("%d ",costflow());//求解最大流
printf("%lld\n",ans);//ans为最小费用
}
int main()
{
init();
work();
}