注意,spfa可能被卡,图中存在负权
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int _ = 2e5+10;
const int N = 1010,inf=0x3f3f3f3f;
void in(int &x){
x=0;int y = 1;
char c=getchar();
while(!isdigit(c)){if(c=='-')y=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
x*=y;
}
void o(int x){
printf("%lld",x);
}
int n,m,k;
int a[_];
//前向星村边,注意始边从2开始,而不再是1。
struct Minicostflow{
// 起始,终点,
int S,T,n;
//边,注意要存u
struct EDG{int u,v,nxt,f,cost;}e[_];int cnt = 1;
int head[_];
// 反边花费为-cos
void add(int u,int v,int f,int cos){
e[++cnt]={u,v,head[u],f,cos};head[u]=cnt;
swap(u,v);
e[++cnt]={u,v,head[u],0,-cos};head[u]=cnt;
}
//spfa 建立分层图
int dis[_],in_queue[_],from[_];
bool spfa(){
for(int i=1;i<=n;i++)dis[i]=inf,in_queue[i]=0;
queue<int>q;q.push(S);dis[S]=0;in_queue[S]=1;
while(!q.empty()){
int u = q.front(); q.pop();
if(u==T)continue;
for(int i=head[u];i;i=e[i].nxt){
EDG P = e[i];
if(P.f&&dis[P.v]>dis[u]+P.cost){
dis[P.v]=dis[u]+P.cost;
from[P.v]=i;
if(!in_queue[P.v]){
in_queue[P.v]=1;
q.push(P.v);
}
}
}
in_queue[u]=0;
}
return dis[T]<inf;
}
// 最大流,最小费用
int maxflow,mincost;
void mincostflow(){
maxflow = mincost = 0;
while(spfa()){
int tmp = inf;
for(int i=T;i!=S;i=e[from[i]].u)tmp = min(tmp,e[from[i]].f);
maxflow+=tmp;mincost+=tmp*dis[T];
for(int i=T;i!=S;i=e[from[i]].u)e[from[i]].f-=tmp,e[from[i]^1].f+=tmp;
}
}
}Minicostflow;
signed main(){
in(n);in(m);in(Minicostflow.S);in(Minicostflow.T);Minicostflow.n=n;
for(int u,v,f,c,i=1;i<=m;i++){
in(u);in(v);in(f);in(c);
Minicostflow.add(u,v,f,c);
}
Minicostflow.mincostflow();
o(Minicostflow.maxflow);putchar(' ');
o(Minicostflow.mincost);putchar('\n');
// o(MAXF.cal());putchar('\n');
return 0;
}