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. JS 将有父子关系的数组转换成树形结构数据

    将类似如下数据转换成树形的数据 [{ id: 1, name: '1', }, { id: 2, name: '1-1', parentId: 1 }, { id: 3, name: '1-1-1', ...

  2. [luogu2607 ZJOI2008] 骑士 (树形dp)

    题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里, ...

  3. python的装饰器,迭代器用法

    装饰器. 装饰器实际就是一个函数 定义:在不改变内部代码和调用方式的基础上增加新的功能 了解装饰器需要了解3个内容: 1.函数即变量 2.高阶函数 1).把一个函数名当作实参传给另一个函数 2).返回 ...

  4. ARM - Linux嵌入式C/C++各种资料分享【更新日期:2012/04/24】

    http://blog.csdn.net/shuxiao9058/article/details/6786868 由于115网盘取消大众分享功能,因此不能继续分享下载链接.更新资料将在本人分享空间转存 ...

  5. C#-WebService基础01

    来自为知笔记(Wiz)

  6. weblogic部署struts2项目訪问action404错误

    近期有个project部署到tomcat上是正常的,部署到weblogic上时訪问action报404错误.依据报错日志.在网上找到了原因例如以下: 部署到weblogic上.struts.xml配置 ...

  7. Collection 和 Collections 的差别?

    Collection 是 java.util 下的接口,它是各种集合的父接口,继承于它的 接口主要有 Set 和 List:Collections 是个 java.util 下的类.是针对集合的 帮助 ...

  8. HDUOj 看病要排队 优先队列的使用 题目1873

    STL优先队列的具体描写叙述 http://blog.csdn.net/yueloveme/article/details/47106639 题目地址:http://acm.hdu.edu.cn/s ...

  9. 屌丝也能开发安卓版2048(App Inventor)

    想编写安卓游戏.java太难.来试试App Inventor.尽管有人觉得他是中学生的玩具,可是也能编写2048这种火爆游戏,不须要太复杂的算法. 整个游戏有几个模块: 一.游戏初始化 数列转化为图形 ...

  10. True or False? and WHY??? Java HashSet Contains

    import java.util.HashSet; public class MyClass { public String s; public MyClass(String s) { this.s ...