UVA10779 Collectors Problem 【迁移自洛谷博客】
这是一道不错的练最大流建模的基础题。
这种题目审题是关键。
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 【迁移自洛谷博客】的更多相关文章
- Uva10491 Cows and Cars 【迁移自洛谷博客】
题目大意 假设有a头牛,b辆车(门的总数为a+b),你先选一个门,然后你最终选择前主持人会替你打开C扇有牛的门(不会打开你已经选择的门),问你要不要换门,输出"总是换门"的策略下, ...
- UVa1636 Headshot 【迁移自洛谷博客】
说明:小蒟蒻hkk现在正在做一些概率的题目,由于这方面和数学还有点关系,所以需要一些数学的思维,也需要表述出来,如夏军所述"把自己给讲懂",所以写了些blog,主要为帮助自己理解. ...
- JSOI2018冬令营游记&总结(迁移自洛谷博客)
游记 一开始在冬令营还没开始的时候,十分期待,殊不知每天都有一场浩劫在等着我. Day0 10:50出发,看见lbn同学发了一条说说,也随便发了一个. 然后在车上一直在睡觉,现在感觉挺后悔的,其实可以 ...
- UVA-10779 Collectors Problem
https://vjudge.net/problem/UVA-10779 题意:n个人,m种贴纸,每个人开始有一些贴纸 第一个人可以跟任何人交换任何贴纸 其余人只能用重复的贴纸 跟第一个人交换他们没有 ...
- UVA10779 Collectors Problem
题目链接:https://cn.vjudge.net/problem/UVA-10779 前言: 本题是关于姜志豪<网络流的一些建模方法>的笔记. 知识点: 最大流 题意摘抄: \(Bob ...
- UVa10779 Collectors Problem(最大流)
很容易想到源点向所类型有贴纸连边,容量为Bob一开始有的数量:然后贴纸向汇点连边,容量为1. 接下来就是交换部分的连边了.注意交换一次一次进行,每次只能交换一张. 交换,是对于两种贴纸而言,仅会发生在 ...
- UVA-10779 Collectors Problem (网络流建模)
题目大意:有n个人,已知每人有ki个糖纸,并且知道每张糖纸的颜色.其中,Bob希望能和同伴交换使得手上的糖纸数尽量多.他的同伴只会用手上的重复的交换手上没有的,并且他的同伴们之间不会产生交换.求出Bo ...
- 洛谷3388 tarjan割点
题目链接:https://www.luogu.com.cn/problem/P3388 tarjan算法果然牛逼,时间复杂度是O(|V|+|E|),所以1e4个结点2e5条边的图完全不在话下orz o ...
- 他是 ISIJ 第四名,也是在线知名题库的洛谷“网红”
转载自加藤惠. 2020年国际初中生信息学竞赛(ISIJ)上,以优秀成绩拿下第四名年仅初三的张湫阳,成为最夺目的选手之一. 而且虽然是初三的选手,但他取得优异成绩后,不少网友并不感到陌生,纷纷留言: ...
随机推荐
- 帝国CMS编辑器粘贴Word图片
图片的复制无非有两种方法,一种是图片直接上传到服务器,另外一种转换成二进制流的base64码 目前限chrome浏览器使用,但是项目要求需要支持所有的浏览器,包括Windows和macOS系统.没有办 ...
- android设置系统默认开机时间
1.设置RTC时间,该时间是如果RCT时钟断电以后使用的默认时间 Android L之前: \alps\mediatek\custom\[project]\preloader\ inc\cust_rt ...
- 2019ICPC上海网络赛A 边分治+线段树
题目: 给定一棵树, 带边权. 现在有2种操作: 1.修改第i条边的权值. 2.询问u到其他一个任意点的最大距离是多少. 解法:边分治+线段树 首先我们将所有的点修改和边修改都存在对应的边里面. 然后 ...
- window安装rsync客户端和服务端
原文地址: https://www.cnblogs.com/janas/p/3321087.html 下载地址: https://linux.linuxidc.com/index.php?folder ...
- (转)dial tcp 10.96.0.1:443: getsockopt: no route to host --- kubernetes(k8s)DNS 服务反复重启
转:https://blog.csdn.net/shida_csdn/article/details/80028905 kubernetes(k8s)DNS 服务反复重启解决: k8s.io/dns/ ...
- git清空远程仓库
需求背景:因为用jenkins连接了git仓库,有时候job构建出现问题,需要排查问题,但是呢,真实的项目代码量非常pang大,所以就需要建1个测试仓库,使用最少量的代码能复现自己的问题就好. 这就需 ...
- JavaScript-[[prototype]]的另一种理解
[[prototype]]简介 javascript 中每一个对象都会有一个特殊的内置属性[[prototype]],这个就是对其他对象对引用.有了这个作为基础去关联其他对象,就能理解继承机制.Chr ...
- HTML--JS 二级联动
<!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...
- Maven系列学习(一)Maven基本知识
Maven 简介 1.Maven主要是基于Java平台的项目构建,依赖管理和项目信息 2.Maven是优秀的构建工具,跨平台,消除构建的重复,抽象了一个完整的构建生命周期模型,标准化构建过程 3.管理 ...
- Oracle基本操作练习(一)
--创建表空间 create tablespace test datafile 'c:\test.dbf' size 100m autoextend on next 10m; --删除表空间 drop ...