最小费用流模板
思路:每次先以价值为边权走一遍SPFA,沿最短路增广。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAXN=501;
const LL MAXM=3e4+10;
const LL INF=0x3f3f3f3f;
LL n,m,s,t,cnt;
LL head[MAXN],vis[MAXN],work[MAXN],dis[MAXN];
LL nxt[MAXM],to[MAXM],w[MAXM],c[MAXM];
queue<LL> q;
LL cost;
pair<LL,LL> ans;
void Add(LL x,LL y,LL f,LL h)
{
nxt[cnt]=head[x];
head[x]=cnt;
to[cnt]=y;
w[cnt]=f;
c[cnt]=h;
cnt++;
}
void add(LL x,LL y,LL f,LL h)
{
Add(x,y,f,h);
Add(y,x,0,-h);
}
bool SPFA()
{
memset(dis,INF,sizeof(dis));
memset(work,0,sizeof(work));
dis[s]=0;
while(!q.empty())
q.pop();
q.push(s);
while(!q.empty())
{
LL u=q.front();
vis[u]=0;
q.pop();
for(LL i=head[u];i!=-1;i=nxt[i])
{
LL v=to[i];
if(dis[v]>dis[u]+c[i]&&w[i])
{
dis[v]=dis[u]+c[i];
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
return dis[t]<INF;
}
LL dfs(LL u,LL dist)
{
if(u==t)
{
cost+=dist*dis[t];
return dist;
}
work[u]=1;
LL res=0;
for(LL i=head[u];i!=-1;i=nxt[i])
{
LL v=to[i];
if(dis[v]==dis[u]+c[i]&&!work[v]&&w[i])
{
LL di=dfs(v,min(dist-res,w[i]));
if(di)
{
w[i]-=di;
w[i^1]+=di;
res+=di;
if(res==dist)
break;
}
}
}
return res;
}
pair<LL,LL> dinic()
{
LL maxf=0;
while(SPFA())
maxf+=dfs(s,INF);
return make_pair(maxf,cost);
}
int main()
{
memset(head,-1,sizeof(head));
memset(nxt,-1,sizeof(nxt));
cin>>n>>m;
s=1,t=n;
for(LL i=1;i<=m;++i)
{
LL x,y,f,h;
cin>>x>>y>>f>>h;
add(x,y,f,h);
}
pair<LL,LL> ans1=dinic();
cout<<ans1.first<<" "<<ans1.second;
return 0;
}