//最裸的最小费用流 #include<iostream> #include<queue> using namespace std; const int MAXN = 105; const int MAXM = 8100; const int INF = 1000000000; int mincost,maxflow; int N,M; int U[MAXM],V[MAXM],cap[MAXM],flow[MAXM],cost[MAXM],next[MAXM]; int head[MAXN],pre[MAXN],Edge[MAXN],dis[MAXN];//Edge记录边的下标 int m; void addEdge(int u,int v,int Cap,int Cost)//每添加一条边,都必须添加他的反向边 { flow[m] = flow[m+1] = 0; V[m] = v; U[m] = u; cap[m] = Cap; cost[m] = Cost; next[m] = head[u]; head[u] = m++; V[m] = u; U[m] = v; cap[m] = 0; cost[m] = -Cost; next[m] = head[v]; head[v] = m++; } void buildGraph() { int u,v,Cap,Cost; m = 0; memset(head,-1,sizeof(head)); for(int i = 2;i <= N;++i) { scanf("%d",&Cost); addEdge(i,N+1,INF,-Cost); } while(M--) { scanf("%d%d%d%d",&u,&v,&Cap,&Cost); addEdge(u,v,Cap,Cost); addEdge(v,u,Cap,Cost); } } void MCMF(int st,int ed) { queue<int> q; memset(flow,0,sizeof(flow)); mincost = maxflow = 0; for(;;) { bool inq[MAXN]; for(int i = st;i <= ed;++i) dis[i] = (i == st ? 0 : INF); memset(inq,0,sizeof(inq)); q.push(st); while(!q.empty()) { int u = q.front(); q.pop(); inq[u] = 0; for(int e = head[u];e != -1;e = next[e]) { if(cap[e] > flow[e] && dis[u] + cost[e] < dis[V[e]]) { dis[V[e]] = dis[u] + cost[e]; pre[V[e]] = U[e]; Edge[V[e]] = e; if(!inq[V[e]]) { q.push(V[e]); inq[V[e]] = 1; } } } }//SPFA增广 if(dis[ed] >= 0) break; int delta = INF;//delta为可改进量 for(int u = ed;u != st;u = pre[u]) delta = min(delta,cap[Edge[u]] - flow[Edge[u]]);//遍历最短路径的边,并修改可改进量 for(int u = ed;u != st;u = pre[u]) { flow[Edge[u]] += delta;//更新正向流量 flow[Edge[u] ^ 1] -= delta;//通过异或取得反向边的序号,并更新反向流量 } mincost += dis[ed] * delta; maxflow += delta; } } int main() { //freopen("in.txt","r",stdin); while(scanf("%d%d",&N,&M) != EOF) { buildGraph(); MCMF(1,N+1); printf("%d/n",-mincost); } return 0; }