Warehouse Keeper

Time Limit: 2000ms
Memory Limit: 65536KB

This problem will be judged on ZJU. Original ID: 2601
64-bit integer IO format: %lld      Java class name: Main

Special Judge
 

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

Andrew Stankevich
 
解题:费用流
 
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <vector>
#include <queue>
#include <cstdlib>
#include <string>
#include <set>
#include <stack>
#define LL long long
#define INF 0x3f3f3f3f
#define pii pair<int,int>
using namespace std;
const int maxn = ;
struct arc{
int to,flow,cost,next;
arc(int x = ,int y = ,int z = ,int nxt = -){
to = x;
flow = y;
cost = z;
next = nxt;
}
};
arc e[maxn*maxn];
int head[maxn],d[maxn],p[maxn],house[maxn];
int tot,S,T,n,m;
bool in[maxn];
int vis[maxn];
vector<int>g[maxn];
void add(int u,int v,int flow,int cost){
e[tot] = arc(v,flow,cost,head[u]);
head[u] = tot++;
e[tot] = arc(u,,-cost,head[v]);
head[v] = tot++;
}
bool spfa(){
queue<int>q;
for(int i = S; i <= T; ++i){
d[i] = INF;
in[i] = false;
p[i] = -;
}
d[S] = ;
q.push(S);
while(!q.empty()){
int u = q.front();
q.pop();
in[u] = false;
for(int i = head[u]; ~i; i = e[i].next){
if(e[i].flow && d[e[i].to] > d[u] + e[i].cost){
d[e[i].to] = d[u] + e[i].cost;
p[e[i].to] = i;
if(!in[e[i].to]){
in[e[i].to] = true;
q.push(e[i].to);
}
}
}
}
return p[T] > -;
}
int solve(int &cost){
int flow = cost = ;
while(spfa()){
int minF = INF;
for(int i = p[T]; ~i; i = p[e[i^].to])
minF = min(minF,e[i].flow);
for(int i = p[T]; ~i; i = p[e[i^].to]){
e[i].flow -= minF;
e[i^].flow += minF;
}
cost += minF*d[T];
flow += minF;
}
return flow;
}
int main(){
int cs,u;
scanf("%d",&cs);
bool cao = false;
while(cs--){
if(cao) puts("");
cao = true;
memset(head,-,sizeof(head));
memset(house,,sizeof(house));
memset(vis,,sizeof(vis));
scanf("%d %d",&m,&n);
S = tot = ;
T = n + m + ;
for(int i = ; i <= T; ++i) g[i].clear();
for(int i = ; i <= m; ++i){
int tmp = ;
scanf("%d",&tmp);
while(tmp--){
scanf("%d",&u);
g[i].push_back(u);
}
}
for(int i = ; i <= m; ++i){
scanf("%d",house+i);
vis[house[i]] = i;
}
for(int i = ; i <= m; ++i){
for(int j = g[i].size()-; j >= ; --j){
int tmp = g[i][j];
if(vis[tmp] == i) add(i,tmp+m,,);
else if(vis[tmp] && vis[tmp] != i) add(i,tmp+m,,);
else add(i,tmp+m,,);
}
}
for(int i = ; i <= m; ++i)
add(S,i,,);
for(int i = ; i <= n; ++i)
add(i+m,T,,vis[i]?-:);
int ans,cost;
ans = solve(cost);
int ahouse[maxn],mb = ;
memset(ahouse,,sizeof(ahouse));
for(int i = ; i < tot; i += ){
if(e[i].to == T || e[i^].to == S ) continue;
if(e[i].flow == ) ahouse[e[i^].to] = e[i].to-m;//cout<<e[i^1].to<<" "<<e[i].to-m<<endl;
}
for(int i = ; i <= m; ++i)
if(house[i] && ahouse[i] != house[i]) mb++;
printf("%d %d\n",ans,mb);
for(int i = ; i <= m; ++i)
printf("%d%c",ahouse[i],i == m ?'\n':' ');
}
return ;
}

ZOJ 2601 Warehouse Keeper的更多相关文章

  1. 2013ACM/ICPC亚洲区南京站现场赛---Poor Warehouse Keeper(贪心)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4803 Problem Description Jenny is a warehouse keeper. ...

  2. Poor Warehouse Keeper

    Poor Warehouse Keeper http://acm.hdu.edu.cn/showproblem.php?pid=4803 Jenny is a warehouse keeper. He ...

  3. hdu 4803 Poor Warehouse Keeper(贪心+数学)

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u011328934/article/details/26005267 题目链接:hdu 4803 P ...

  4. HDU 4803 Poor Warehouse Keeper (贪心+避开精度)

    555555,能避开精度还是避开精度吧,,,,我们是弱菜.. Poor Warehouse Keeper Time Limit: 2000/1000 MS (Java/Others)    Memor ...

  5. HDU 4803 Poor Warehouse Keeper

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4803 解题报告:有一个记录器,一共有两个按钮,还有两行屏幕显示,第一行的屏幕显示的是数目,第二行的屏幕 ...

  6. HDU4803_Poor Warehouse Keeper

    题目很有意思,我想说其实我在比赛的时候就看过了一下这个题目,今天才这么快搞出来吧. 其实总共按上键的次数不会超过10个,我们可以每次假设相隔按两次上键之间按了xi次下键,由于上键的次数是确定的,所以最 ...

  7. 【贪心】hdu4803 Poor Warehouse Keeper

    题意:一开始有1个物品,总价是1.你的一次操作可以要么使得物品数量+1,总价加上当前物品的单价.要么可以使得总价+1,物品数量不变.问你最少要几次操作从初始状态到达有x个物品,总价是y的状态.这里的y ...

  8. HDU 4803 Poor Warehouse Keeper(贪心)

    题目链接 题意 :屏幕可以显示两个值,一个是数量x,一个是总价y.有两种操作,一种是加一次总价,变成x,1+y:一种是加一个数量,这要的话总价也会相应加上一个的价钱,变成x+1,y+y/x.总价显示的 ...

  9. HDU - 4803 - Poor Warehouse Keeper (思维)

    题意: 给出x,y两个值分别代表x个物品,总价为y 有两种变化: 1.使总价+1,数量不变 2.数量+1,总价跟着变化 (y = y + y / x) 思路: 给出目标x,y,计算最少变化次使数量变化 ...

随机推荐

  1. [NOIP补坑计划]NOIP2017 题解&做题心得

    终于做完了…… 场上预计得分:?(省一分数线:295) 由于看过部分题解所以没有预计得分qwq 题解: D1T1 小凯的疑惑 题面 震惊!一道小学奥数题竟难倒无数高中考生! 欢迎大家以各种姿势*和谐* ...

  2. Qt编程—去掉标题栏和设置窗口透明用法

    学习Qt编程,有时候我们很想做出好看又比较炫的画面,这时就常用到qt上的一些技巧. 这里我以一个小例子来展示qt的这些技巧,此qt编程写的,如图:(去掉标题栏和设置窗口透明后) 代码实现部分: .h文 ...

  3. JavaScript中的常用的数组操作方法

    JavaScript中的常用的数组操作方法 一.concat() concat() 方法用于连接两个或多个数组.该方法不会改变现有的数组,仅会返回被连接数组的一个副本. var arr1 = [1,2 ...

  4. java拷贝字符文件

    1.java拷贝字符文件 2.代码如下: package Demo1; import java.io.*; public class copyfile { public static void mai ...

  5. Android学习JNI,使用JNI实现字符串加密

    本节学习使用C语言加密字符串,大家都知道使用JAVA实现的加密都能够反编译的,而使用C写的加密是非常难被反编译的.所以我们使用JNI学习怎样使用C实现对字符串的加密. 首先:我们实现一个界面 布局文件 ...

  6. IOS7 textkit 的相关

    去年基于5.0开发的时候.自己用coreText编写了一个富文本,全部的效果都实现的非常好.可是没有去測试效率.只是在cell重用的时候表现不错.在4s上面也不会卡顿. 唯一一个问题就是,在使用AL的 ...

  7. 省赛i题/求1~n内全部数对(x,y),满足最大公约数是质数的对数

    求1~n内全部数对(x,y),gcd(x,y)=质数,的对数. 思路:用f[n]求出,含n的对数.最后用sum[n]求和. 对于gcd(x,y)=a(设x<=y,a是质数),则必有gcd(x/a ...

  8. 安卓通过OkHttp获取json数据

    使用Http协议访问网络 OkHttp使用 可以很好的获取接口数据!json数据! 支持get和post提交方式!!! 1.引入模块 compile 'com.squareup.okhttp3:okh ...

  9. js中console强大之处体现在哪

    js中console强大之处体现在哪 一.总结 一句话总结:在我用过的浏览器当中,我是最喜欢Chrome的,因为它对于调试脚本及前端设计调试都有它比其它浏览器有过之而无不及的地方.可能大家对conso ...

  10. Install the high performance Nginx web server on Ubuntu

    Look out Apache, there's a web server – Nginx (pronounced Engine X) – that means to dismantle you as ...