这是一道不错的练最大流建模的基础题。
这种题目审题是关键。
Bob’s friends will only exchange stickers with Bob, and they will give away only
duplicate stickers in exchange with different stickers they don’t possess.
意思就是说,Bob的朋友们只会和Bob交换贴纸,并且呢,他们只会赠送给Bob他们有的重复的的贴纸,以换取他们没有的贴纸。
上面还有一段话,But Bob is clever: he has realized that in some cases it is good for him to trade one of his duplicate stickers for a sticker he already possesses.就是说,Bob他可能会有自己重复的贴纸去换他已经有的贴纸。(这样就可以再用这一张贴纸去换其他他没有的贴纸了)

题目问的是Bob最多可以得到多少贴纸。

很明显,根据以往的经验,这是一个网络流的模型。我们应该把所有的人,所有的贴纸都用一个点来表示一下。任何贴纸之间应该怎么建边呢? 首先,把一个人(Bob除外),向他可以交换给别人的贴纸(数量>=2)上建边,容量应该为他所拥有此类贴纸数量-1。

然后也可以把一个贴纸向所有不具有它的人连一条边,容量为1(因为每种贴纸一个人只会要一次),表示把这个贴纸交换过来了。这样一来,我们每流过一个点,一定是进来一次,出来一次,可以很好地表示一次交换。

但是这个成立前提是什么呢?这些贴纸肯定是从Bob开始交换的,也是最后流回Bob的手里的。那么,Bob本人也应该向她所拥有的贴纸建边,边权为他拥有的这类贴纸的数量。为什么不用减1呢?这个问题我们留到后面来解决。

我们还需要再建一个点T,让所有的贴纸都指向T,边权为1。因为每一类贴纸只算一次。我们就可以用从Bob到这个点T的最大流表示Bob可以收集到的贴纸最多有多少类了。其实T这个点,也是用来表示Bob这个人的另一个点。

现在让我们汇过来看刚刚那一个问题。因为Bob的贴纸种类,最终是通过刚刚我们建的那个点T来统计的,所以我们必须把这个留下的贴纸也流过去。就算这个贴纸被换成了其他贴纸了,那也不会影响结果——因为我们建立的这个网络,不会让一类贴纸流到两次到T的,因此即使那个贴纸被换成了其他贴纸,这个贴纸还是唯一的,不会影响总的种类数。

为了便于大家理解,我来画个图。

上面三个图,是样例二的模型。其中S是Bob,BC是其他两个人。1234是四种贴纸(题目说有5中,但第五种没有出现)。为了便于分清边的方向,从两边到中间的边是黑色的,从中间到两边的是蓝色的。
每个图加粗的边都是一个单位的流,流一和流三这样从S流到T可以很好地表示Bob本来就有这样的一个贴纸。流二则可以很形象地表示Bob把一张贴纸1和B换来一个贴纸2,有把这个贴纸2从C出换来贴纸3。

这样的话,每一个单位的流,就表示一种贴纸的来龙去脉,如此,最大流是几,就可以表示Bob最多可以收集到多少种贴纸。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std; const int maxn=10+7,maxm=25+7,INF=0x7f7f7f7f;
int Test,Cas,n,m,x,y,S,T;
int cnt[maxm]; int head[maxn+maxm],tot=-1;
struct Edge{int u,v,flow,ne;}g[maxm*maxn<<4];
inline void addedge(int x,int y,int z){
g[++tot].u=x;g[tot].v=y;g[tot].flow=z;g[tot].ne=head[x];head[x]=tot;
g[++tot].u=y;g[tot].v=x;g[tot].flow=0;g[tot].ne=head[y];head[y]=tot;
} int cur[maxn+maxm],dist[maxn+maxm];queue<int>q;
bool bfs(int s,int t){
memset(dist,0x7f,sizeof(dist));dist[s]=0;q.push(s);for(register int i=S;i<=T;++i)cur[i]=head[i];
while(!q.empty()){int x=q.front();q.pop();for(register int i=head[x];~i;i=g[i].ne)if(g[i].flow&&dist[g[i].v]==INF)dist[g[i].v]=dist[x]+1,q.push(g[i].v);}
return dist[t]<INF;
}
int dfs(int x,int t,int a){
if(x==t||!a)return a;int flow=0,f;
for(register int &i=cur[x];~i;i=g[i].ne)if(dist[g[i].v]==dist[x]+1&&(f=dfs(g[i].v,t,min(a,g[i].flow)))){g[i].flow-=f;g[i^1].flow+=f;flow+=f;a-=f;if(!a)break;}
return flow;
}
inline int Dinic(int s,int t){int ans=0;while(bfs(s,t))ans+=dfs(s,t,INF);return ans;}
//上面是Dinic部分,不用说了吧
void Clear(){tot=-1;memset(head,-1,sizeof(head));} void Init(){
Clear();scanf("%d%d",&n,&m);S=1,T=n+m+1;
for(register int i=1;i<=n;++i){
scanf("%d",&x);memset(cnt,0,sizeof(cnt));for(register int j=1;j<=x;++j){scanf("%d",&y);++cnt[y];}//cnt用来统计这个人有每种贴纸多少张
if(i==1)for(register int j=1;j<=m;++j){if(cnt[j])addedge(S,j+n,cnt[j]);}//1就是Bob,这里把Bob向他有的贴纸建边
else for(register int j=1;j<=m;++j)if(cnt[j]>1)addedge(i,j+n,cnt[j]-1);else if(!cnt[j])addedge(j+n,i,1);//如果这个人有这种贴纸多于1张,就可以用来和别人交换其他贴纸,因此和这种贴纸建边。否则,若此人没有这种贴纸,就可以从别人那里获得,就让那种贴纸向他建边
}
for(register int i=1;i<=m;++i)addedge(i+n,T,1);//每种贴纸向终点建边
} void Work(){
printf("Case #%d: %d\n",++Cas,Dinic(S,T));
} int main(){
scanf("%d",&Test);
while(Test--){
Init();
Work();
}
}

——发表于2018-04-24 15:01:53

UVA10779 Collectors Problem 【迁移自洛谷博客】的更多相关文章

  1. Uva10491 Cows and Cars 【迁移自洛谷博客】

    题目大意 假设有a头牛,b辆车(门的总数为a+b),你先选一个门,然后你最终选择前主持人会替你打开C扇有牛的门(不会打开你已经选择的门),问你要不要换门,输出"总是换门"的策略下, ...

  2. UVa1636 Headshot 【迁移自洛谷博客】

    说明:小蒟蒻hkk现在正在做一些概率的题目,由于这方面和数学还有点关系,所以需要一些数学的思维,也需要表述出来,如夏军所述"把自己给讲懂",所以写了些blog,主要为帮助自己理解. ...

  3. JSOI2018冬令营游记&总结(迁移自洛谷博客)

    游记 一开始在冬令营还没开始的时候,十分期待,殊不知每天都有一场浩劫在等着我. Day0 10:50出发,看见lbn同学发了一条说说,也随便发了一个. 然后在车上一直在睡觉,现在感觉挺后悔的,其实可以 ...

  4. UVA-10779 Collectors Problem

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

  5. UVA10779 Collectors Problem

    题目链接:https://cn.vjudge.net/problem/UVA-10779 前言: 本题是关于姜志豪<网络流的一些建模方法>的笔记. 知识点: 最大流 题意摘抄: \(Bob ...

  6. UVa10779 Collectors Problem(最大流)

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

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

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

  8. 洛谷3388 tarjan割点

    题目链接:https://www.luogu.com.cn/problem/P3388 tarjan算法果然牛逼,时间复杂度是O(|V|+|E|),所以1e4个结点2e5条边的图完全不在话下orz o ...

  9. 他是 ISIJ 第四名,也是在线知名题库的洛谷“网红”

    转载自加藤惠. 2020年国际初中生信息学竞赛(ISIJ)上,以优秀成绩拿下第四名年仅初三的张湫阳,成为最夺目的选手之一. 而且虽然是初三的选手,但他取得优异成绩后,不少网友并不感到陌生,纷纷留言: ...

随机推荐

  1. oracle 字段信息

    oracle 修改字段的长度alter table tablename modify column_name varchar2(32)alter table tablename modify (col ...

  2. sql-hive笔试题整理 1 (学生表-成绩表-课程表-教师表)

    题记:一直在写各种sql查询语句,最长的有一百多行,自信什么需求都可以接,可......,想了想,可能一直在固定的场景下写,平时也是以满足实际需求为目的,竟不知道应试的题都是怎么出的,又应该怎么做.遂 ...

  3. 点击" ./start_navicat"安装出现界面便面为乱码

    环境:ubuntu16.4 下载Navicat:navicat112_mariadb_cs_x64.tar.gz 点击" ./start_navicat"安装出现界面便面为乱码 解 ...

  4. 129、TensorFlow计算图的可视化

    import tensorflow as tf # Build your graph x = tf.constant([[37.0, -23.0], [1.0, 4.0]], name="i ...

  5. Jquery浅析

    目录 jquery 通过jquery改变标签字体颜色 jquery和js对象之间值转化 Jquery基本选择器 Jquery层级选择器 基本筛选器 操作类属性 模太框 表单筛选器 筛选器方法 设置多个 ...

  6. 深入学习Keras中Sequential模型及方法

    https://www.cnblogs.com/wj-1314/p/9579490.html

  7. HTTP 协议解析

    目录 目录 HTTP 协议 HTTP 协议工作原理 HTTP Request 请求行 Request Header HTTP Response 状态行 Response Header Body HTT ...

  8. Gitlab仓库搭建和免密使用gitlab

    Gitlab简介 GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务. 可通过Web界面进行访问公开的或者私人项目.它拥有与Github类似的 ...

  9. 数据挖掘与CRM

    数据挖掘与CRM 现在的数据挖掘项目多数都是游击战,这边挖一挖那边挖一挖,挖到最后还是一场空,还落了个"忽悠"绰号:回想数据挖掘的一个标准流程,那只是一个数据挖掘类项目的标杆而已, ...

  10. upc组队赛17 Stone Game【极小值】

    Stone Game 题目链接 题目描述 Alice and Bob are always playing game! The game today is about taking out stone ...