题意:
为了追求ACM比赛的公平性,所有用作ACM比赛的电脑性能是一样的,而ACM董事会专门有一条生产线来生产这样的电脑,随着比赛规模的越来越大,生产线的生产能力不能满足需要,所以说ACM董事会想要重新建造一条生产线。
生产线是全自动化的,所以需要机器来组成生产线,给定有多少中种机器,标准ACM用电脑有多少部份,每种机器将什么样的ACM电脑半成品处理成什么样的电脑半成品(对于输入的电脑半成品,每部分有0,1,2三种状态:代表着 0、这部分必须没有我才能处理,1、这部分必须有我才能处理,2、这部分有没有我都能处理。对于输出的电脑半成品有0,1两种状态:代表着0,处理完后的电脑半成品里没有这部分,1、处理完的电脑半成品有这部分),每一个机器每小时可以处理Q个半成品(输入数据中的Qi)。
求组装好的成产线的最大工作效率(每小时最多生成多少成品,成品的定义就是所有部分的状态都是“1”)
第一行输入两个数:一个P代表有P个零件, 一个 N代表有N台机器。
接下来N行,每行第一个数字有Qi,代表 第i个零件每小时能加工的半成品零件个数。然后是2*P个数字,前P个数字是加工前半成品需要满足的条件,后P个数表示加工后的半成品的数量。
===========================================================================
思路:
首先要把点分割开,把点分开成两部分的意义在于,不能让最大流量超过本身的生产量。


==============================================================================================================
由第一副图可知,假如我们不拆分点,那么到达F的流量就是30, 主要原因是流经C点的时候,我们的总流量是超过C可以处理的最大流量的,但是每一个自流量是小于C能处理的最大流量的,但是我们又无法加以限制。因此会出现这样的问题。第二幅图我们就将拆点了,将C到C' 之间的流量加以限制。这样就不会超过最大流量。
==============================================================================================
最后我们这道题目处理出来的模型是这样的(和二分匹配可):

============================================================================================================
最后一个点就是如何输出路径。
路径的输出是要保存两个图,保存原图,和做完Dinic之后的残余网路图。
然后用原图减去残余网路图如果边权值大于0,说明这个边上曾经有过流量。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<queue> using namespace std; typedef long long LL; const int INF = 1e9+7; const int maxn = 2005; const int MOD = 1e9+7; int G[maxn][maxn], Layer[maxn], G2[maxn][maxn]; struct node { int in[12], out[12];///第i台机器的输入输出规格 int flow;///第i台机器能放出的最大流量 } P[maxn]; int n, m;///n台机器,每台机器需要m个零件 bool OK(int a,int b) { for(int i=1; i<=m; i++) { if( !(P[a].out[i] == P[b].in[i] || P[b].in[i] == 2) ) return false; } return true; } bool BFS(int Star,int End) { memset(Layer, 0, sizeof(Layer)); Layer[Star] = 1; queue<int> Q; Q.push(Star); while( Q.size() ) { int s = Q.front(); Q.pop(); if(s == End) return true; for(int i=0; i<= End; i++) { if(G[s][i] && !Layer[i]) { Layer[i] = Layer[s] + 1; Q.push(i); } } } return false; } int DFS(int s,int End, int MaxFlow) { if(s == End) return MaxFlow; int sFlow = 0;///从s出发到达汇点的最大流量 for(int i=0; i<=End; i++) { int flow = G[s][i]; if( G[s][i]==0 || Layer[s]+1 != Layer[i] ) continue; flow = min(MaxFlow-sFlow, flow); flow = DFS(i, End, flow); G[s][i] -= flow; G[i][s] += flow; sFlow += flow; if(sFlow == MaxFlow) break ; } if(sFlow == 0) Layer[s] = 0; return sFlow; } int Dinic(int Star,int End) { int ans = 0; while( BFS(Star, End) ) { ans += DFS(Star, End, INF); } return ans; } int main() { while(scanf("%d %d", &m, &n) != EOF) { memset(G, 0, sizeof(G)); memset(P, 0, sizeof(P)); for(int i=1; i<=n; i++) { scanf("%d", &P[i].flow); for(int j=1; j<=m; j++) scanf("%d", &P[i].in[j]); for(int j=1; j<=m; j++) scanf("%d", &P[i].out[j]); } for(int i=1; i<=m; i++) { P[0].in[i] = P[0].out[i] = 0; P[n+1].in[i] = P[n+1].out[i] = 1; } P[0].flow = P[n+1].flow = INF; n ++; for(int i=0; i<=n; i++) for(int j=0; j<=n; j++) { if(i == j) G[j+n][i] = P[i].flow; else if( OK(i, j) ) G[i][j+n] = P[i].flow; } memcpy(G2, G, sizeof(G)); int MaxFlow = Dinic(0, n*2); int num = 0, a[maxn], b[maxn], c[maxn]; for(int i=1; i<n; i++) for(int j=1; j<n; j++) { if(i == j)continue; if(G2[i][j+n] > G[i][j+n]) { a[num] = i, b[num] = j; c[num++] = G2[i][j+n] - G[i][j+n]; } } printf("%d %d ", MaxFlow, num); for(int i=0; i<num; i++) printf("%d %d %d ", a[i], b[i], c[i]); } return 0; } /* 3 5 5 0 0 0 0 1 0 100 0 1 0 1 0 1 3 0 1 0 1 1 0 1 1 0 1 1 1 0 300 1 1 2 1 1 1 */