最大流dinic板子
const int N = 1e6+10, S = N-2, T = N-1, INF = 0x3f3f3f3f;
int n;
struct edge {
int to,w,next;
edge(int to=0,int w=0,int next=0):to(to),w(w),next(next){}
} e[N];
int head[N], dep[N], vis[N], cur[N], cnt=1;
queue<int> Q;
int bfs() {
REP(i,1,n) dep[i]=INF,vis[i]=0,cur[i]=head[i];
dep[S]=INF,vis[S]=0,cur[S]=head[S];
dep[T]=INF,vis[T]=0,cur[T]=head[T];
dep[S]=0,Q.push(S);
while (Q.size()) {
int u = Q.front(); Q.pop();
for (int i=head[u]; i; i=e[i].next) {
if (dep[e[i].to]>dep[u]+1&&e[i].w) {
dep[e[i].to]=dep[u]+1;
Q.push(e[i].to);
}
}
}
return dep[T]!=INF;
}
int dfs(int x, int w) {
if (x==T) return w;
int used = 0;
for (int i=cur[x]; i; i=e[i].next) {
cur[x] = i;
if (dep[e[i].to]==dep[x]+1&&e[i].w) {
int f = dfs(e[i].to,min(w-used,e[i].w));
if (f) used+=f,e[i].w-=f,e[i^1].w+=f;
if (used==w) break;
}
}
return used;
}
int dinic() {
int ans = 0;
while (bfs()) ans+=dfs(S,INF);
return ans;
}
void add(int u, int v, int w) {
e[++cnt] = edge(v,w,head[u]);
head[u] = cnt;
e[++cnt] = edge(u,0,head[v]);
head[v] = cnt;
}
费用流EK+spfa板子
const int N = 1e6+10, INF = 0x3f3f3f3f, S = N-2, T = N-1;
int n, m, flow, cost;
struct edge {
int to,w,v,next;
edge(int to=0,int w=0,int v=0,int next=0):to(to),w(w),v(v),next(next){}
} e[N];
int head[N], dep[N], vis[N], cur[N], f[N], cnt=1;
int pre[N],pre2[N];
queue<int> Q;
int spfa() {
REP(i,1,n) f[i]=dep[i]=INF,vis[i]=0;
f[S]=dep[S]=f[T]=dep[T]=INF;
dep[S]=0,Q.push(S);
while (Q.size()) {
int u = Q.front(); Q.pop();
vis[u] = 0;
for (int i=head[u]; i; i=e[i].next) {
if (dep[e[i].to]>dep[u]+e[i].v&&e[i].w) {
dep[e[i].to]=dep[u]+e[i].v;
pre[e[i].to]=u,pre2[e[i].to]=i;
f[e[i].to]=min(f[u],e[i].w);
if (!vis[e[i].to]) {
vis[e[i].to]=1;
Q.push(e[i].to);
}
}
}
}
return dep[T]!=INF;
}
void EK(){
while(spfa()) {
int w = f[T];
for (int u=T; u!=S; u=pre[u]) {
e[pre2[u]].w-=w;
e[pre2[u]^1].w+=w;
}
flow += w, cost += w*dep[T];
}
}
void add(int u, int v, int w, int k) {
e[++cnt] = edge(v,w,k,head[u]);
head[u] = cnt;
e[++cnt] = edge(u,0,-k,head[v]);
head[v] = cnt;
}
费用流dinic+dijkstra板子
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#define REPP(i,a,b,d) for(int i=a; i<=b; i+=d)
#define REP(i,a,b) REPP(i,a,b,1)
#define REVV(i,a,b,d) for(int i=a; i>=b; i-=d)
#define REV(i,a,b) REVV(i,a,b,1)
#define FOR(i,n) for(int i=0; i<n; i++)
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
#define pb push_back
#define mp make_pair
#define F first
#define S second
const int OO = 1e9;
// end of macro
const int N = 1e5+10;
int SRC, SINK, n, m;
struct edge{int to, flow, cap, cost;};
vector<edge>edges;
vi lse[N];
void addEdge(int a, int b, int cap, int cost){
lse[a].pb(edges.size());
edges.pb({b, 0, cap, cost});
lse[b].pb(edges.size());
edges.pb({a, 0, 0, -cost}); // here cap=0, cannot make 2 way, have to call this function twice, because of cost
}
int level[N]; // to prevent infinite loop during dfs
int potential[N];
int dist[N];
int lastEdge[N];
int ccost(int now, edge& e){ // compute cost w/ potentials
return e.cost + potential[now] - potential[e.to];
}
// almost like dinic's bfs, but dijkstra instead
bool dijkstra(){
REP(i,1,n) {
potential[i] += dist[i];
dist[i] = -1;
level[i] = 0;
}
priority_queue<pii>pq;
level[SRC] = 0;
pq.push(mp(0, SRC));
dist[SRC] = 0;
while(!pq.empty()){
int d = -pq.top().F;
int now = pq.top().S;
pq.pop();
if(dist[now] != d)continue;
FOR(i,lse[now].size()){
edge& e = edges[lse[now][i]];
if(e.flow < e.cap){
if(dist[e.to] != -1 && dist[e.to] <= d+ccost(now, e))continue;
dist[e.to] = d+ccost(now, e);
level[e.to] = max(level[e.to], level[now]+1);
pq.push(mp(-d-ccost(now, e), e.to));
}
}
}
return dist[SINK] != -1;
}
int dfs(int now, int flow){ // do the flow
if(now == SINK)return flow;
//printf("at %d, flow %d\n",now,flow);
int ret = 0;
for(int& i = lastEdge[now]; i<lse[now].size(); i++){
edge& e = edges[lse[now][i]];
if(level[e.to] <= level[now])continue; //going back
if(e.flow == e.cap)continue; // no flow
if(dist[e.to] == dist[now] + ccost(now, e)){
//printf("%d -> %d\n",now,e.to);
int curr = dfs(e.to, min(flow, e.cap - e.flow));
if(curr > 0){
e.flow += curr; // forward flow
edges[lse[now][i]^1].flow -= curr; // residual
flow -= curr;
ret += curr;
if(flow == 0)return ret; // if flow to this node is already depleted, i.e. there is a bottleneck far before this node
}
}
}
return ret;
}
int totalflow, totalcost;
void MCMF(){
totalflow = totalcost = 0;
while(dijkstra()) {
//printf("dist %d\n",dist[SINK] + potential[SINK]);
//REP(i,1,n*m)printf("%d = %d\n",i,dist[i]+potential[i]);
REP(i,1,n) lastEdge[i]=0;
lastEdge[SRC]=lastEdge[SINK]=0;
int flow = dfs(SRC, OO);
totalflow += flow;
totalcost += flow * (dist[SINK] + potential[SINK]);
}
}
int main() {
scanf("%d%d%d%d", &n, &m, &SRC, &SINK);
REP(i,1,m) {
int u,v,w,f;
scanf("%d%d%d%d",&u,&v,&w,&f);
addEdge(u,v,w,f);
}
MCMF();
printf("%d %d\n",totalflow,totalcost);
}