ZOJ 2601 Warehouse Keeper
Warehouse Keeper
64-bit integer IO format: %lld Java class name: Main
The company where Jerry works owns a number of warehouses that can be used to store various goods. For each warehouse the types of goods that can be stored in this warehouse are known. To avoid problems with taxes, each warehouse must store only one type of goods, and each type of goods must be stored in at most one warehouse.
Jerry is planning to receive a new lot of goods in a couple of days and he must store the goods in the warehouses. However there are some goods in some warehouses already and Jerry wants to move as few of them as possible.
Help him to find the maximal number of types of goods that he can store in the warehouses and the minimal number of goods he must move in order to do that.
Input
The input contains multiple test cases. The first line of the input is a single integer T (1 <= T <= 40) which is the number of test cases. T test cases follow, each preceded by a single blank line.
The first line of each test case contains integer numbers m and n (2 <= m, n <= 200) - the number of warehouses and the number of types of goods respectively.
The following m lines describe warehouses. Each line contains ki - the number of various types of goods that can be stored in this warehouse (remember, only one type of goods can be stored in a warehouse at a time), followed by ki integer numbers - the types of goods that can be stored.
The last line contains m integer numbers - for each warehouse either 0 is provided if there is no goods in this warehouse, or the type of goods that is currently stored in this warehouse if there is one. It is guaranteed that the initial configuration is correct, that is, each warehouse stores the goods it can store, and no type of goods is stored in more than one warehouse.
Output
For each case, on the first line print p - the maximal number of types of goods that can be stored in the warehouses, and q - the minimal number of goods that need to be moved in order to do that. After that output m integer numbers - for each warehouse output the type of goods that must be stored in this warehouse, or 0 if none must be.
Remember that you may only move goods that are already stored in some houses to other ones, you are not allowed to dispose them.
Two consecutive cases should be separated by a single blank line. No blank line should be produced after the last test case.
Sample Input
2 4 5 3 1 2 3 2 1 2 2 1 2 3 1 4 5 0 2 0 1 2 2 1 1 1 2 0 0
Sample Output
4 1 3 2 1 4 2 0 1 2
Source
Author
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <climits> 7 #include <vector> 8 #include <queue> 9 #include <cstdlib> 10 #include <string> 11 #include <set> 12 #include <stack> 13 #define LL long long 14 #define INF 0x3f3f3f3f 15 #define pii pair<int,int> 16 using namespace std; 17 const int maxn = 500; 18 struct arc{ 19 int to,flow,cost,next; 20 arc(int x = 0,int y = 0,int z = 0,int nxt = -1){ 21 to = x; 22 flow = y; 23 cost = z; 24 next = nxt; 25 } 26 }; 27 arc e[maxn*maxn]; 28 int head[maxn],d[maxn],p[maxn],house[maxn]; 29 int tot,S,T,n,m; 30 bool in[maxn]; 31 int vis[maxn]; 32 vector<int>g[maxn]; 33 void add(int u,int v,int flow,int cost){ 34 e[tot] = arc(v,flow,cost,head[u]); 35 head[u] = tot++; 36 e[tot] = arc(u,0,-cost,head[v]); 37 head[v] = tot++; 38 } 39 bool spfa(){ 40 queue<int>q; 41 for(int i = S; i <= T; ++i){ 42 d[i] = INF; 43 in[i] = false; 44 p[i] = -1; 45 } 46 d[S] = 0; 47 q.push(S); 48 while(!q.empty()){ 49 int u = q.front(); 50 q.pop(); 51 in[u] = false; 52 for(int i = head[u]; ~i; i = e[i].next){ 53 if(e[i].flow && d[e[i].to] > d[u] + e[i].cost){ 54 d[e[i].to] = d[u] + e[i].cost; 55 p[e[i].to] = i; 56 if(!in[e[i].to]){ 57 in[e[i].to] = true; 58 q.push(e[i].to); 59 } 60 } 61 } 62 } 63 return p[T] > -1; 64 } 65 int solve(int &cost){ 66 int flow = cost = 0; 67 while(spfa()){ 68 int minF = INF; 69 for(int i = p[T]; ~i; i = p[e[i^1].to]) 70 minF = min(minF,e[i].flow); 71 for(int i = p[T]; ~i; i = p[e[i^1].to]){ 72 e[i].flow -= minF; 73 e[i^1].flow += minF; 74 } 75 cost += minF*d[T]; 76 flow += minF; 77 } 78 return flow; 79 } 80 int main(){ 81 int cs,u; 82 scanf("%d",&cs); 83 bool cao = false; 84 while(cs--){ 85 if(cao) puts(""); 86 cao = true; 87 memset(head,-1,sizeof(head)); 88 memset(house,0,sizeof(house)); 89 memset(vis,0,sizeof(vis)); 90 scanf("%d %d",&m,&n); 91 S = tot = 0; 92 T = n + m + 1; 93 for(int i = 0; i <= T; ++i) g[i].clear(); 94 for(int i = 1; i <= m; ++i){ 95 int tmp = 0; 96 scanf("%d",&tmp); 97 while(tmp--){ 98 scanf("%d",&u); 99 g[i].push_back(u); 100 } 101 } 102 for(int i = 1; i <= m; ++i){ 103 scanf("%d",house+i); 104 vis[house[i]] = i; 105 } 106 for(int i = 1; i <= m; ++i){ 107 for(int j = g[i].size()-1; j >= 0; --j){ 108 int tmp = g[i][j]; 109 if(vis[tmp] == i) add(i,tmp+m,1,0); 110 else if(vis[tmp] && vis[tmp] != i) add(i,tmp+m,1,1); 111 else add(i,tmp+m,1,0); 112 } 113 } 114 for(int i = 1; i <= m; ++i) 115 add(S,i,1,0); 116 for(int i = 1; i <= n; ++i) 117 add(i+m,T,1,vis[i]?-10:0); 118 int ans,cost; 119 ans = solve(cost); 120 int ahouse[maxn],mb = 0; 121 memset(ahouse,0,sizeof(ahouse)); 122 for(int i = 0; i < tot; i += 2){ 123 if(e[i].to == T || e[i^1].to == S ) continue; 124 if(e[i].flow == 0) ahouse[e[i^1].to] = e[i].to-m;//cout<<e[i^1].to<<" "<<e[i].to-m<<endl; 125 } 126 for(int i = 1; i <= m; ++i) 127 if(house[i] && ahouse[i] != house[i]) mb++; 128 printf("%d %d\n",ans,mb); 129 for(int i = 1; i <= m; ++i) 130 printf("%d%c",ahouse[i],i == m ?'\n':' '); 131 } 132 return 0; 133 }