解题报告 之 ZOJ2332 Gems

来源:互联网 发布:雨林木风xp优化工具 编辑:程序博客网 时间:2024/05/22 16:48

解题报告 之 ZOJ2332 Gems


Description

Wealthy alsomagic! 
Supernatural alsomagic! 
But also poor alsomagic! 
Because he is now puzzled by a problem, and will go crazy if you can't help him.

alsomagic has a lot of gems with different colors and shapes. His supernatural power provides him the ability of transforming some gems' shape and color! Now he wants to give some of gems to his darling girlfriend as gift. But a problem came with him. His girlfriend dislikes too many gems with the same color! And alsomagic, will also be disgusted with lots of gems with the same shape.

So he attempts to change some gems to solve this problem.

Input

The first line of a multiple input is an integer T, followed by T input blocks. The first line of each input block are two integers N, M (1 =< N,M <= 10) indicating alsomagic has N different shapes of gems with M different colors, then N lines of integers follow, each line contains M integers. The integer K in row R column C states that alsomagic has K number of gems with shape R and color C.

Follow this is integer D, then D lines of integers. Each line contains four integers R1 C1 R2 C2(0 =< R1, R2 < N, 0 <= C1, C2 < M) indicating one kind of transfor way, by which he can change some of shape R1, color C1 gems to shape R2, color C2, and VICE VERSA. But each way of transform can only be used ONCE!

Then N integers, the K-th integer is the number of gems with SHAPE K that alsomagic can tolerance.
Then M integers. The K-th integer is the number of gems with COLOR K that alsomagic's girlfriend can tolerance!

Output

One line percase, with "Yes" if there is a way to solve this problem, otherwise "No".

Sample Input



1 3 
3 2 6 

0 1 0 2 

1 3 2 

1 3 
3 2 6 

0 1 0 2 

1 3 2 

Sample Output

Yes 
No 

题目大意:石头有n种,m种形状。现在告诉你有着第 i 种形状,有第 j 种形状的石头有多少个,要你把他们按照一定要求分成两堆。特别地,有一些转化。能将R1形状C1颜色的石头转化为R2形状C2颜色的石头。分堆的要求是第一堆的第c种颜色不能超过tc种,而第二堆的第 s 种形状不能超过ts种。问你是否存在一种分配方案。

分析:首先吐槽出题人的英语也是有够魔性。说都说不清楚。首先alsomagic对形状的要求不说清楚是对送出去的还是剩下的,这样根本理解不了题意。第二那个转化魔法use once 没说清楚是只能改变一个石头,还是只能选择使用一个转化方向,还是每个方向只能一次且可转化随意数量的石头。事实证明是第三个意思。

好吧,言归正传。最大流嘛很明显。一开始我以为形状和颜色女友都有要求,于是乎老师构图不出。所以我们如下构图。超级源点连接每种石头(颜色或形状不同都算一种,则最多有100种:10*10),负载为该种石头的数量。然后形状一样石头分别连接到对应的形状汇总节点,也就是200+1~200+n。同理,颜色一样的石头分别连接到 300+1~300+m节点(我间隔一般取得大而不想老是用n、m来算)。并将所有形状汇总节点和颜色汇总节点分别连接到形状总结点803和颜色总结点804。803和804连接到超级汇点。然后转化魔法就连接两种石头即可,负载为INF。最后跑最大流看看超级汇点的流量是否等于石头总数,是的话就Yes,否则No。

上代码:
#include<iostream>#include<cstring>#include<algorithm>#include<queue>#include<cstdio>#include<sstream>#include<string>using namespace std;const int MAXN = 810;const int MAXM = 11000;const int INF = 0x3f3f3f3f;struct Edge{int from, to, cap, next;};Edge edge[MAXM];int level[MAXN];int head[MAXN];int src, des, cnt= 0;void addedge( int from, int to, int cap ){edge[cnt].from = from;edge[cnt].to = to;edge[cnt].cap = cap;edge[cnt].next = head[from];head[from] = cnt++;swap( from, to );edge[cnt].from = from;edge[cnt].to = to;edge[cnt].cap = 0;edge[cnt].next = head[from];head[from] = cnt++;}int bfs( ){memset( level, -1, sizeof level );queue<int> q;while (!q.empty( ))q.pop( );level[src] = 0;q.push( src );while (!q.empty( )){int u = q.front( );q.pop( );for (int i = head[u]; i != -1; i = edge[i].next){int v = edge[i].to;if (edge[i].cap&&level[v] == -1){level[v] = level[u] + 1;q.push( v );}}}return level[des] != -1;}int dfs( int u, int f ){if (u == des) return f;int tem;for (int i = head[u]; i != -1; i = edge[i].next){int v = edge[i].to;if (edge[i].cap&&level[v] == level[u] + 1){tem = dfs( v, min( f, edge[i].cap ) );if (tem > 0){edge[i].cap -= tem;edge[i ^ 1].cap += tem;return tem;}}}level[u] = -1;return 0;}int Dinic( ){int ans = 0, tem;while (bfs( )){while (tem = dfs( src, INF )){ans += tem;}}return ans;}int main( ){int kase,total=0;cin >> kase;src = 0, des = 805;while (kase--){memset( head, -1, sizeof head );cnt = 0;total = 0;int n, m;cin >> n >> m;for (int i = 0; i < n; i++){for (int j = 1; j <= m; j++){int gem;cin >> gem;total += gem;addedge( src, i * 10 + j, gem );addedge( i * 10 + j, i + 200 + 1, INF );addedge( i * 10 + j, j + 300, INF );}}int change;cin >> change;while (change--){int s1, c1, s2, c2;cin >> s1 >> c1 >> s2 >> c2;c1++;c2++;addedge( s1 * 10 + c1, s2 * 10 + c2 , INF );addedge( s2 * 10 + c2, s1 * 10 + c1 , INF );}for (int i = 1; i <= n; i++){int ts;cin >> ts;addedge( 200 + i, 803, ts );}for (int i = 1; i <= m; i++){int tc;cin >> tc;addedge( 300 + i, 804, tc );}addedge( 803, 805, INF );addedge( 804, 805, INF );if (Dinic() == total)cout << "Yes" << endl;elsecout << "No" << endl;}return 0;}


0 0