题意:树上每个节点上有若干苹果,边上带权,问你最小费用使得书上的苹果方差最小。
思路:上下费用流问题,参考http://blog.csdn.net/qq564690377/article/details/8870587
代码如下:
1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last modified : 2014-05-13 12:02 5 * Filename : zoj_3231_2.cpp 6 * Description : 7 * ************************************************/ 8 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 #include <cstdlib> 13 #include <cmath> 14 #include <algorithm> 15 #include <queue> 16 #include <stack> 17 #include <vector> 18 #include <set> 19 #include <map> 20 #define MP(a, b) make_pair(a, b) 21 #define PB(a) push_back(a) 22 23 using namespace std; 24 typedef long long ll; 25 typedef pair<int, int> pii; 26 typedef pair<unsigned int,unsigned int> puu; 27 typedef pair<int, double> pid; 28 typedef pair<ll, int> pli; 29 typedef pair<int, ll> pil; 30 31 const int INF = 0x3f3f3f3f; 32 const double eps = 1E-6; 33 const int MAXN = 10000; 34 const int MAXM = 100000; 35 struct Edge{int to,next,cap,flow,cost;}edge[MAXM]; 36 int head[MAXN],tol; 37 int pre[MAXN],dis[MAXN]; 38 bool vis[MAXN]; 39 int N;//节点总个数,节点编号从0~N-1 40 41 void init(int n) 42 { 43 N = n; 44 tol = 0; 45 memset(head,-1,sizeof(head)); 46 } 47 48 void addedge(int u,int v,int cap,int cost) 49 { 50 edge[tol].to = v; 51 edge[tol].cap = cap; 52 edge[tol].cost = cost; 53 edge[tol].flow = 0; 54 edge[tol].next = head[u]; 55 head[u] = tol++; 56 edge[tol].to = u; 57 edge[tol].cap = 0; 58 edge[tol].cost = -cost; 59 edge[tol].flow = 0; 60 edge[tol].next = head[v]; 61 head[v] = tol++; 62 } 63 bool spfa(int s,int t) 64 { 65 queue<int>q; 66 for(int i = 0; i < N; i++) 67 { 68 dis[i] = INF; 69 vis[i] = false; 70 pre[i] = -1; 71 } 72 dis[s] = 0; 73 vis[s] = true; 74 q.push(s); 75 while(!q.empty()) 76 { 77 int u = q.front(); 78 q.pop(); 79 vis[u] = false; 80 for(int i = head[u]; i != -1; i = edge[i].next) 81 { 82 int v = edge[i].to; 83 if(edge[i].cap > edge[i].flow && 84 dis[v] > dis[u] + edge[i].cost ) 85 { 86 dis[v] = dis[u] + edge[i].cost; 87 pre[v] = i; 88 if(!vis[v]) 89 { 90 vis[v] = true; 91 q.push(v); 92 } 93 } 94 } 95 } 96 if(pre[t] == -1)return false; 97 else return true; 98 } 99 //返回的是最大流,cost存的是最小费用 100 int minCostMaxflow(int s,int t,int &cost) 101 { 102 int flow = 0; 103 cost = 0; 104 while(spfa(s,t)) 105 { 106 int Min = INF; 107 for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) 108 { 109 if(Min > edge[i].cap - edge[i].flow) 110 Min = edge[i].cap - edge[i].flow; 111 } 112 for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) 113 { 114 edge[i].flow += Min; 115 edge[i^1].flow -= Min; 116 cost += edge[i].cost * Min; 117 } 118 flow += Min; 119 } 120 return flow; 121 } 122 123 int main() 124 { 125 // freopen("in.txt", "r", stdin); 126 int a, b, n, vex[101], val, sum; 127 while(scanf("%d", &n)!=EOF){ 128 sum = 0; 129 for(int i=1; i<=n; i++){ 130 scanf("%d", &vex[i]); 131 sum += vex[i]; 132 } 133 init(n+3); 134 for(int i=1; i<n; i++){ 135 scanf("%d%d%d", &a, &b, &val); 136 a++, b++; 137 addedge(a, b, INF, val); 138 addedge(b, a, INF, val); 139 } 140 for(int i=1; i<=n; i++){ 141 addedge(0, i, vex[i], 0); 142 addedge(i, n+1, sum/n, 0); 143 addedge(i, n+2, 1, 0); 144 } 145 addedge(n+2, n+1, sum%n, 0); 146 int ans; 147 minCostMaxflow(0, n+1, ans); 148 printf("%d ", ans); 149 } 150 return 0; 151 }