最小费用最大流。
开始用邻接矩阵做的,无奈死活WA,应该是两个城市的边不止一条 = =。。。无奈邻接表没写过,网上搜了个能理解的模板,学习之。。。
里面有个异或求反向边的,如果a是偶数,a^1 = a+1 。a是奇数,a^1 = a-1。正好是建图的时候的反向边。。
还有要注意的时候,就是建图的时候,这个是双向的。。。
建立一个汇点,把最后卖出的价钱取负值当做费用,然后求最短路,答案取负即可。
#include <cstdio> #include <cstdlib> #include <iostream> #include <string.h> #include <queue> #include <limits.h> #define MAX 105 using namespace std; typedef struct NODE{ int from,to,cap,cost; int next; }NODE; NODE node[MAX*MAX]; int beer[MAX]; int cou,n,m; void init() { memset(beer,0,sizeof(beer)); memset(node,'/0',sizeof(node)); cou = 2; } void Add(int u,int v,int cap,int cost) { node[cou].from = u; node[cou].to = v; node[cou].cap = cap; node[cou].cost = cost; node[cou].next = beer[u]; beer[u] = cou++; node[cou].from = v; node[cou].to = u; node[cou].cap = 0; node[cou].cost = -cost; node[cou].next = beer[v]; beer[v] = cou++; } int MincostMaxflow(int s,int t) { queue<int> q; int inq[MAX],pre[MAX],dis[MAX],re[MAX]; int u,v,i,a,c = 0,ind,cost,cap; while(1) { memset(inq,0,sizeof(inq)); for(i=s; i<=t; i++) dis[i] = INT_MAX; dis[s] = 0; inq[s] = 1; pre[s] = s; q.push(s); while( !q.empty() ) { u = q.front(); q.pop(); inq[u] = 0; ind = beer[u]; while( ind != 0 ) { u = node[ind].from; v = node[ind].to; cost = node[ind].cost; cap = node[ind].cap; if( cap > 0 && dis[v] > dis[u] + cost ) { dis[v] = dis[u] + cost; pre[v] = u; re[v] = ind; if( !inq[v] ) { q.push(v); inq[v] = 1; } } ind = node[ind].next; } } if( dis[t] >= 0 ) break; a = INT_MAX; for(u=t; u!=s; u=pre[u]) if( node[re[u]].cap < a ) a = node[re[u]].cap; for(u=t; u!=s; u=pre[u]) { node[re[u]^1].cap += a; node[re[u]].cap -= a; } c += dis[t]*a; } return -c; } int main() { int i,ans,from,to,c,pay,earn; while( scanf("%d%d",&n,&m) != EOF ) { init(); for(i=2; i<=n; i++) { scanf("%d",&earn); Add(i,n+1,INT_MAX,-earn); } for(i=1; i<=m; i++) { scanf("%d%d%d%d",&from,&to,&c,&pay); Add(from,to,c,pay); Add(to,from,c,pay); } ans = MincostMaxflow(1,n+1); printf("%d/n",ans); } return 0; }