链接:http://acm.hust.edu.cn/vjudge/problem/36866题意:对于一个R行C列的正整数矩阵(1≤R,C≤20),设Ai为前i行所有元素之和,Bi为前i列所有元素之和。已知R,C和数组A和B,找一个满足条件的矩阵。矩阵中的元素必须是1~20之间的正整数。输入保证有解。分析:这道题主要还是考查建模能力。如何把一个矩阵模型转化成网络流模型是关键之处。首先注意到矩阵任意行或列的元素之和是不变的(设第i行元素之和为Ai′,第i列元素之和为Bi′),因此想到把矩阵的每行和每列都看成是一个结点,然后增设一个源点s和一个汇点t,并将矩阵中的每个元素减1,
然后从源点s向各个行结点Xi连一条弧,那么容量为Ai′-C(由于先前使每个元素减去1每行总的减去C,使得s到Xi的容量下界为0上界为Ai′-C),从各个列结点Yi向t连一条弧,容量为Bi′-R(同理),对于每个矩阵元素(Xi,Yj),从结点Xi向Yj连一条弧,容量为19,接下来就是求s-t的最大流,有解的条件是s出发和到达t都要满载,原因是每行和每列的元素之和是不变的,格子(i,j)的值就是结点Xi->Yj的流量加上1(先前每个元素都减去了1)。
1 #include <cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<vector> 5 #include<algorithm> 6 using namespace std; 7 8 const int maxn = 40 + 5; 9 const int INF = 1000000000; 10 11 struct Edge { 12 int from, to, cap, flow; 13 Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {} 14 }; 15 16 struct EdmondsKarp { 17 int n, m; 18 vector<Edge> edges; 19 vector<int> G[maxn]; 20 int a[maxn]; 21 int p[maxn]; 22 23 void init(int n) { 24 for (int i = 0; i < n; i++) G[i].clear(); 25 edges.clear(); 26 } 27 28 void AddEdge(int from, int to, int cap) { 29 edges.push_back(Edge(from, to, cap, 0)); 30 edges.push_back(Edge(to, from, 0, 0)); 31 m = edges.size(); 32 G[from].push_back(m - 2); 33 G[to].push_back(m - 1); 34 } 35 36 int Maxflow(int s, int t) { 37 int flow = 0; 38 for (;;) { 39 memset(a, 0, sizeof(a)); 40 queue<int> Q; 41 Q.push(s); 42 a[s] = INF; 43 while (!Q.empty()) { 44 int x = Q.front(); Q.pop(); 45 for (int i = 0; i < G[x].size(); i++) { 46 Edge& e = edges[G[x][i]]; 47 if (!a[e.to] && e.cap > e.flow) { 48 p[e.to] = G[x][i]; 49 a[e.to] = min(a[x], e.cap - e.flow); 50 Q.push(e.to); 51 } 52 } 53 if (a[t]) break; 54 } 55 if (!a[t]) break; 56 for (int u = t; u != s; u = edges[p[u]].from) { 57 edges[p[u]].flow += a[t]; 58 edges[p[u] ^ 1].flow -= a[t]; 59 } 60 flow += a[t]; 61 } 62 return flow; 63 } 64 }; 65 66 EdmondsKarp g; 67 int idex[maxn][maxn]; 68 69 int main() { 70 int T; 71 scanf("%d", &T); 72 for (int kase = 1; kase <= T; kase++) { 73 int r, c; 74 scanf("%d%d", &r, &c); 75 g.init(r + c + 2); 76 int v, last = 0; 77 for (int i = 1; i <= r; i++) { 78 scanf("%d", &v); 79 g.AddEdge(0, i, v - last - c); 80 last = v; 81 } 82 last = 0; 83 for (int i = 1; i <= c; i++) { 84 scanf("%d", &v); 85 g.AddEdge(r + i, r + c + 1, v - last - r); 86 last = v; 87 } 88 for (int i = 1; i <= r; i++) 89 for (int j = 1; j <= c; j++) { 90 g.AddEdge(i, r + j, 19); 91 idex[i][j] = g.edges.size() - 2; 92 } 93 g.Maxflow(0, r + c + 1); 94 printf("Matrix %d\n", kase); 95 for (int i = 1; i <= r; i++) { 96 for (int j = 1; j <= c; j++) 97 printf("%d ", g.edges[idex[i][j]].flow + 1); 98 putchar(‘\n‘); 99 } 100 putchar(‘\n‘); 101 } 102 return 0; 103 }
时间: 2024-10-12 07:54:46