费用流 建图很简单直接上代码
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} #define MAXN 110 #define MAXD 50000 const int INF = 0x3f3f3f3f; int P,I; int G[MAXN][MAXN]; queue<int>q; struct node { int u,v,next; int cap,flow,cost; }edge[MAXD]; int cnt,src,tag; int head[MAXN]; int p[MAXN],d[MAXN]; bool inq[MAXN]; int nump[MAXN],numi[MAXN]; void addedge(int u ,int v, int cap ,int cost) { edge[cnt].u = u; edge[cnt].v = v; edge[cnt].flow = 0; edge[cnt].cap = cap; edge[cnt].cost = cost; edge[cnt].next = head[u]; head[u] = cnt++; edge[cnt].v = u; edge[cnt].u = v; edge[cnt].flow= 0; edge[cnt].cap = 0; edge[cnt].cost = - cost; edge[cnt].next = head[v]; head[v] = cnt++; } bool SPFA(int s,int t) { while (!q.empty()) q.pop(); memset(inq,false,sizeof(inq)); memset(d,0x3f,sizeof(d)); memset(p,-1,sizeof(p)); inq[s] = true; d[s] = 0; q.push(s); while (!q.empty()) { int u = q.front();q.pop(); inq[u] = false; for (int i = head[u] ; i != - 1; i = edge[i].next) { int v = edge[i].v; if (d[v] > d[u] + edge[i].cost && edge[i].cap > edge[i].flow) { d[v] = d[u] + edge[i].cost; p[v] = i; if (!inq[v]) { inq[v] = true; q.push(v); } } } } return d[t] != INF; } int slove() { int C = 0 ,F = 0; while (SPFA(src,tag)) { int a = INF; for (int i = p[tag]; i != -1 ; i = p[edge[i].u]) a = min(a,edge[i].cap - edge[i].flow); for (int i = p[tag]; i != -1; i = p[edge[i].u]) { edge[i].flow += a; edge[i ^ 1].flow -= a; } C += d[tag] * a; F += a; } return C; } int main() { //freopen("sample.txt","r",stdin); int kase = 1; while (scanf("%d%d",&P,&I) != EOF) { if (P == 0 && I == 0) break; for (int i = 1; i <= P; i++)scanf("%d",&nump[i]); for (int i = 1; i <= I; i++) scanf("%d",&numi[i]); cnt = 0; memset(head ,-1 ,sizeof(head)); src = 0; tag = P + I + 1; for (int i = 1 ;i <= P; i++) for (int j = 1; j <= I; j++) { double tmp; scanf("%lf",&tmp); if (tmp < - 0.5) G[i][j] = -100; else { tmp = (tmp * 100 + 0.5); G[i][j] = (int) tmp; } } int retmin,retmax; for (int i = 1; i <= P; i++) addedge(src,i,nump[i],0); for (int i = 1; i <= I; i++) addedge(P + i , tag ,numi[i],0); for (int i = 1; i <= P; i++) for (int j = 1; j <= I; j++) { if (G[i][j] == -100) continue; addedge(i , P + j ,INF,G[i][j]); } retmin = slove(); cnt = 0; memset(head,-1,sizeof(head)); for (int i = 1; i <= P; i++) addedge(src,i,nump[i],0); for (int i = 1; i <= I; i++) addedge(P + i , tag ,numi[i],0); for (int i = 1; i <= P; i++) for (int j = 1; j <= I; j++) { if (G[i][j] == -100) continue; addedge(i , P + j ,INF,-G[i][j]); } retmax = -1 * slove(); printf("Problem %d: %.2lf to %.2lf ",kase++,(double)retmin / 100.0,(double) retmax / 100.0); } return 0; }