题目链接:https://cn.vjudge.net/problem/UVA-10779

前言:

  本题是关于姜志豪《网络流的一些建模方法》的笔记。

知识点:  最大流

题意摘抄:

  \(Bob\) 和他的朋友从糖果包装里收集贴纸。\(Bob\) 和他的朋友总共 \(n\) 人。共有 \(m\) 种不同的贴纸。

  每人手里都有一些(可能有重复的)贴纸,并且只跟别人交换他所没有的贴纸。贴纸总是一对一交换。

  \(Bob\) 比这些朋友更聪明,因为他意识到只跟别人交换自己没有的贴纸并不总是最优的。在某些情况下,换来一张重复贴纸更划算。

  假设 \(Bob\) 的朋友只和 \(Bob\) 交换(他们之间不交换),并且这些朋友只会出让手里的重复贴纸来交换他们没有的不同贴纸。你的任务是帮助 \(Bob\) 算出他最终可以得到的不同贴纸的最大数量。

  \((2 \le n le 10, 5 \le m \le 25)\)

解题思路:

  每种贴纸、每个朋友都各视为一个点,再加上一个源点和一个汇点。

  对于每种贴纸,建一条从源点到这种贴纸的边,容量为 \(Bob\) 所拥有的这种贴纸的张数;

  对于每一个朋友,如果他没有某种贴纸,就建一条从这种贴纸到他的边,容量为 \(1\);如果他有这种贴纸并且拥有量 \(k\) 大于\(1\) ,则建一条从他到这种贴纸的边,容量为 \(k-1\).

  对于每种贴纸,再建一条边到汇点,容量为 \(1\).

AC代码:

 #include <bits/stdc++.h>
using namespace std;
const int MAXN = ;//点数的最大值
const int MAXM = ;//边数的最大值
const int INF = 0x3f3f3f3f; struct Edge{
int to,next,cap,flow;
}edge[MAXM];//注意是MAXM
int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],cur[MAXN];
void init(){
tol = ;
memset(head,-,sizeof(head));
}
void addedge(int u,int v,int w,int rw = ){
edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = ;
edge[tol].next = head[u]; head[u] = tol++;
edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = ;
edge[tol].next = head[v]; head[v] = tol++;
}
int Q[MAXN];
void BFS(int start,int end){
memset(dep,-,sizeof(dep));
memset(gap,,sizeof(gap));
gap[] = ;
int front = , rear = ;
dep[end] = ;
Q[rear++] = end;
while(front != rear){
int u = Q[front++];
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;
if(dep[v] != -)
continue;
Q[rear++] = v;
dep[v] = dep[u] + ;
gap[dep[v]]++;
}
}
}
int S[MAXN];
int sap(int start,int end,int N){
BFS(start,end);
memcpy(cur,head,sizeof(head));
int top = ;
int u = start;
int ans = ;
while(dep[start] < N){
if(u == end){
int Min = INF;
int inser;
for(int i = ;i < top;i++)
if(Min > edge[S[i]].cap - edge[S[i]].flow){
Min = edge[S[i]].cap - edge[S[i]].flow;
inser = i;
}
for(int i = ;i < top;i++){
edge[S[i]].flow += Min;
edge[S[i]^].flow -= Min;
}
ans += Min;
top = inser;
u = edge[S[top]^].to;
continue;
}
bool flag = false;
int v;
for(int i = cur[u]; i != -; i = edge[i].next){
v = edge[i].to;
if(edge[i].cap - edge[i].flow && dep[v]+ == dep[u]){
flag = true;
cur[u] = i;
break;
}
}
if(flag){
S[top++] = cur[u];
u = v;
continue;
}
int Min = N;
for(int i = head[u]; i != -; i = edge[i].next)
if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min){
Min = dep[edge[i].to];
cur[u] = i;
}
gap[dep[u]]--;
if(!gap[dep[u]])
return ans;
dep[u] = Min + ;
gap[dep[u]]++;
if(u != start)
u = edge[S[--top]^].to;
}
return ans;
}
int has[];
int main(){
int T;
int n,m,k;
int num;
int kase=;
scanf("%d",&T);
while(T--){
init();
int s=,t=MAXN-;
memset(has,,sizeof(has));
scanf("%d%d",&n,&m);
scanf("%d",&k);
while(k--){
scanf("%d",&num);
has[num]++;
}
for(int i=;i<=m;i++){
addedge(s,i,has[i]);
addedge(i,t,);
}
for(int i=;i<n;i++){
memset(has,,sizeof(has));
scanf("%d",&k);
while(k--){
scanf("%d",&num);
has[num]++;
}
for(int j=;j<=m;j++){
if(!has[j])
addedge(j,+i,);
else if(has[j]>)
addedge(+i,j,has[j]-);
}
}
printf("Case #%d: %d\n",kase++,sap(s,t,+m+n));
}
return ;
}

UVA10779 Collectors Problem的更多相关文章

  1. UVA-10779 Collectors Problem

    https://vjudge.net/problem/UVA-10779 题意:n个人,m种贴纸,每个人开始有一些贴纸 第一个人可以跟任何人交换任何贴纸 其余人只能用重复的贴纸 跟第一个人交换他们没有 ...

  2. UVa10779 Collectors Problem(最大流)

    很容易想到源点向所类型有贴纸连边,容量为Bob一开始有的数量:然后贴纸向汇点连边,容量为1. 接下来就是交换部分的连边了.注意交换一次一次进行,每次只能交换一张. 交换,是对于两种贴纸而言,仅会发生在 ...

  3. UVA-10779 Collectors Problem (网络流建模)

    题目大意:有n个人,已知每人有ki个糖纸,并且知道每张糖纸的颜色.其中,Bob希望能和同伴交换使得手上的糖纸数尽量多.他的同伴只会用手上的重复的交换手上没有的,并且他的同伴们之间不会产生交换.求出Bo ...

  4. UVA10779 Collectors Problem 【迁移自洛谷博客】

    这是一道不错的练最大流建模的基础题. 这种题目审题是关键. Bob's friends will only exchange stickers with Bob, and they will give ...

  5. [Bob]Collectors Problem

    https://vjudge.net/problem/UVA-10779#author=0 网络流 1.Bob向他有的贴纸连边,流量为他有的贴纸数量 2.每一种贴纸向汇点连流量为1的边 3.其余人,如 ...

  6. UVA 10779 Collectors Problem(最大流)

    这个题是很难往网络流上面构思的... 从s向每个物品增加容量为Bob拥有数的弧,然后从每个物品向t增加容量为1的弧(代表种类个数).这时候跑最大流的话,得到的肯定是Bob拥有的初始种类数.那么交换后的 ...

  7. uva 10779 Collectors Problem 网络流

    链接 一共有n个人, m种收藏品, 每个人拥有的收藏品的种类和个数都是不相同的. 假设2-n这些人都只和1互相交换, 比例是1:1, 并且, 2-n这些人, 只换自己现在没有的, 如果他现在有第二种, ...

  8. AC日记——Collectors Problem uva 10779

    UVA - 10779 思路: 最大流: s向所有的贴纸的种类连边,流量为Bob拥有的数量: 然后,Bob的朋友如果没有这种贴纸,则这种贴纸向bob的朋友连边,容量1: 如果bob的朋友的贴纸很多大于 ...

  9. UVA10779Collectors Problem

    uva 10779 Collectors Problem Some candy manufacturers put stickers into candy bar packages. Bob and ...

随机推荐

  1. Fabric的6大特性

    文章目录 什么是Hyperledger Fabric 1. 成员准入 2. 性能,可伸缩性和信任级别 3 需要了解的数据 4 通过不可变的分布式账本进行复杂查询 5 支持插件组件的模块化架构 6 保护 ...

  2. Scala教程之:Either

    在之前的文章中我们提到了Option,scala中Option表示存在0或者1个元素,如果在处理异常的时候Option就会有很大的限制,因为Option如果返回None,那么我并不知道具体的异常到底是 ...

  3. 徐州I

    #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #defi ...

  4. 【Linux网络基础】TCP/IP 协议簇(各个常见协议介绍)

    一.应用层协议 1. FTP   协议所在层次:应用层协议 名称:FTP协议 协议端口:20,21 协议说明: FTP(File Transfer Protocol,文件传输协议)是TCP/IP协议组 ...

  5. CF思维联系– CodeForces -CodeForces - 992C Nastya and a Wardrobe(欧拉降幂+快速幂)

    Nastya received a gift on New Year - a magic wardrobe. It is magic because in the end of each month ...

  6. CodeForces - 1245 C - Constanze's Machine

    Codeforces Round #597 (Div. 2) Constanze is the smartest girl in her village but she has bad eyesigh ...

  7. Python(Pyautogui 模块)

    1.安装 pyautogui 模块 pip install pyautogui 2.pyautogui 模块相关操作 鼠标操作 # 获取屏幕宽和高 w,h = pyautogui.size() # 在 ...

  8. MySQL必知必会1-20章读书笔记

    MySQL备忘 目录 目录 使用MySQL 检索数据 排序检索数据 过滤数据 数据过滤 用通配符进行过滤 用正则表达式进行搜索 创建计算字段 使用数据处理函数 数值处理函数 汇总数据 分组数据 使用子 ...

  9. 深度优先搜索理论基础与实践(java)

    概论 深度优先搜索属于图算法的一种,是一个针对图和树的遍历算法,英文缩写为 DFS 即 Depth First Search.深度优先搜索是图论中的经典算法,利用深度优先搜索算法可以产生目标图的相应拓 ...

  10. Spring IOC的核心机制:实例化与注入

    上文我们介绍了IOC和DI,IOC是一种设计模式,DI是它的具体实现,有很多的框架都有这样的实现,本文主要以spring框架的实现,来看具体的注入实现逻辑. spring是如何将对象加入容器的 spr ...