#include #define rep(i,n) for(int i=0;i<(n);i++) using namespace std; using lint=long long; const int V_MAX=100001; const int CAPA_INF=1<<29; const lint COST_INF=1LL<<61; template struct edge{ int v,rev; capa_t capa; cost_t cost; capa_t flow; }; template void add_directed_edge(vector< edge > *G,int u,int v,capa_t capa,cost_t cost){ G[u].push_back((edge){v,G[v].size() ,capa, cost,0}); G[v].push_back((edge){u,G[u].size()-1, 0,-cost,0}); } template pair augment(int n,vector< edge > *G,int s,int t,cost_t *pot){ static int pre[V_MAX]; static cost_t d[V_MAX]; rep(u,n) d[u]=(u==s?0:COST_INF); // Dijkstra bool ok=false; priority_queue< pair > Q; Q.push(make_pair(0,s)); while(!Q.empty()){ int u=Q.top().second; cost_t cost=-Q.top().first; Q.pop(); if(cost &e=G[u][i]; cost_t cost2=cost+e.cost+pot[u]-pot[e.v]; if(e.capa-e.flow>0 && cost2 &e1=G[v][pre[v]]; edge &e2=G[e1.v][e1.rev]; water=min(water,e2.capa-e2.flow); v=e1.v; } cost_t cost=0; for(int v=t;v!=s;){ edge &e1=G[v][pre[v]]; edge &e2=G[e1.v][e1.rev]; e1.flow-=water; e2.flow+=water; cost+=water*e2.cost; v=e1.v; } rep(u,n) pot[u]+=d[u]; return make_pair(water,cost); } template pair primal_dual(int n,vector< edge > *G,int s,int t){ static cost_t pot[V_MAX]; rep(u,n) pot[u]=0; capa_t ans1=0; cost_t ans2=0; while(1){ pair tmp=augment(n,G,s,t,pot); if(tmp.first==0) break; ans1+=tmp.first; ans2+=tmp.second; } return make_pair(ans1,ans2); } int main(){ int n,m; scanf("%d%d",&n,&m); vector> G[V_MAX]; rep(i,m){ int u,v; lint c1,c2; scanf("%d%d%lld%lld",&u,&v,&c1,&c2); u--; v--; add_directed_edge(G,u,v,1,c1); add_directed_edge(G,u,v,1,c2); add_directed_edge(G,v,u,1,c1); add_directed_edge(G,v,u,1,c2); } add_directed_edge(G,n-1,n,2,0LL); printf("%lld\n",primal_dual(n+1,G,0,n).second); return 0; }