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. Extjs win

    //创建window var win = Ext.create("Ext.window.Window", { id: "myWin", title: " ...

  2. for循环+setTimeout的延迟操作

    例子: for (var i = 0; i < 5; i++) { setTimeout(function () { console.log(i); }, 100) } 上述代码,输出结果显而易 ...

  3. c 最简单的链表

    #include <stdio.h> struct node { int data; struct node *next; //指向本身的指针 }; // main() { struct ...

  4. Node.js 指南(迁移到安全的Buffer构造函数)

    迁移到安全的Buffer构造函数 移植到Buffer.from()/Buffer.alloc() API. 概述 本指南介绍了如何迁移到安全的Buffer构造函数方法,迁移修复了以下弃用警告: 由于安 ...

  5. jQuery 简单介绍

    jQuery  简单介绍 jQuery的定义 jQuery是一个快速,小巧,功能丰富的JavaScript库.它通过易于使用的API在大量浏览器中运行,使得   HTML文档遍历和操作,事件处理,动画 ...

  6. 简述Vue的响应式原理

    当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化.每个组 ...

  7. [terry笔记]Python字符串

    如下学习python的字符串用法. print(dir(str)) ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', ...

  8. Java String.replaceAll()方法

    声明  以下是java.lang.String.replaceAll()方法的声明 public String replaceAll(String regex, String replacement) ...

  9. oauth2.0里回调地址返回code中如何让code不显示在URL里?

    背景: 最近在调用对方提供的oauth2.0接口的时候,返回code在URL显示,但是会影响到本系统调用其他的菜单项的操作,所以想把返回的code值去掉. 解决办法:     想了各种解决办法,目前把 ...

  10. HDU 4308 Contest 1

    纯BFS+优先队列扩展. #include <iostream> #include <cstdio> #include <cstring> #include < ...