/*
学了好几天了,终于生成了模板
一直以来有一个问题没有克服,今天终于想明白了,那就是为什么要加反向流量呢?
那是因为如果你在加流量的时候如果加多了,,则要溜回去。。。。
*/
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100000;
const int inf = 0x777777;
struct {
int head;
}H[maxn];
struct {
int u,v,next,cap,cost;
}E[10*maxn];
int top;
void add(int u,int v,int cap,int cost) {
E[top].v = v;E[top].cap = cap;
E[top].cost = cost;
E[top].next = H[u].head;
H[u].head = top++;
}
int d[maxn];
int p[maxn];
int vis[maxn];
int path[maxn];
int max_flow,ans;
bool spfa(int s,int t,int n)
{
for(int i=1;i<=n;i++)
d[i] = inf;
d[s] = 0;
memset(vis,0,sizeof(vis));
queue <int> q;
q.push(s);vis[s] = 1;
while(!q.empty())
{
int x = q.front();q.pop();vis[x] = 0; //cout<<x<<endl;
for(int i=H[x].head;i!=-1;i = E[i].next)
{
if(E[i].cap > 0 && d[E[i].v] > d[x]+E[i].cost)
{
d[E[i].v] = d[x]+E[i].cost;
path[E[i].v] = i; //这个地方很是关键,记录当前边的编号
p[E[i].v] = x;
if(!vis[E[i].v])
{
vis[E[i].v] = 1;
q.push(E[i].v);
}
}
}
}
if(d[t] == inf) return false;
int u = t,sum = inf;
while (u!=s) {
sum = min(E[path[u]].cap,sum);
u = p[u];
}
u = t;
max_flow += sum;
while(u != s) { // 更新正反流量
E[path[u]].cap -= sum;
E[path[u]^1].cap += sum;
ans += E[path[u]].cost * sum;
u = p[u];
}
return true;
}
void init()
{
memset(H,-1,sizeof(H));
memset(E,-1,sizeof(E));
top = 0;
ans = 0;
max_flow = 0;
}
int main()
{
int n,m,k;
int u,v,cost,cap;
while(~scanf("%d%d%d",&n,&m,&k))
{
init();
while(m--)
{
scanf("%d%d%d%d",&u,&v,&cost,&cap);
for(int i=1;i<=cap;i++)
{
add(u,v,1,cost*(2*i-1));
add(v,u,0,-cost*(2*i-1));
}
}
add(0,1,k,0);
add(1,0,0,0);
while(spfa(0,n,n));
if(max_flow<k)
printf("-1\n");
else
printf("%d\n",ans);
}
}
最小费用最大流 hdu 3667
最新推荐文章于 2019-04-11 22:28:52 发布