点此看题面

大致题意: 有\(n\)种药,每种药有一个权值,且使用了若干种药材。让你选择若干种药,使得药的数量与所使用的药材并集大小相等,求最小权值总和。

网络流

\(hl666\):这种数据范围,一眼网络流!

然后我们两个画了半天硬是想不出一种合适的建图方式。。。

于是就默默打开了题解。。。

可惜题解里讲得都不是很详细,蒟蒻我表示难以理解,最后想了很久才搞明白为什么要这样做,且这样做为什么对。

因此,我会讲得较为详细一些,把所有让我思考了很久的地方都解释清楚。

建图

考虑从源点向每种药分别连一条容量为\(INF\)减去其权值的边,然后从每种药向对应的药材,从每种药材向汇点,分别连一条流量为\(INF\)的边。

然后,我们求出最小割(即跑一遍最大流),并用其减去从源点向外连出的边的容量总和即为答案。

看完是不是一脸懵逼?为什么边权都要设成\(INF\)级别?为什么这样求出最小割就能求出答案?

让我们先来借助样例,来大致感受一下按照这样建图有什么神奇效果:

此时,原图中的最小割为割去\(s->1,s->2,3'->t\),共为\(3*INF-10\)。

而从源点向外连出的边的容量总和为\(3*INF-7\),因此相减得到\(-3\),即答案。

是不是感到很神奇?

关于建图的具体解释

接下来,我们来具体解释一下这样建图的好处及作用,也就是这样建图的一些性质。

连接药与药材的边绝不会被选作最小割中的边

考虑到你一个药会向不少于\(1\)种药材连边,所以连接药与药材的边数显然是大于或等于药材数的。

则你设想如果一条连接药与药材的边被选作了最小割中的边,则显然,割去它没有割去它所连接的药材与汇点的连边更优

原因是这条边只不过是连向该药材的一条边,你割去了这条边,其他边可能依然能流通。而你割去了该药材与汇点的连边,则所有连向该药材的边都断流了。

退一步说,即使没有其他连向该药材的边,考虑到这条边与该药材连向汇点的边流量相同,因此割去这两条边就是等价的,因此依然可以看作是割去了该药材与汇点的连边。

该性质得证。

则我们可由此推知,被选作最小割中的边一定是从源点向某种药的连边从某种药材向汇点的连边

割去一条边的实际意义

接下来,我们来考虑一下割去一条边的实际意义。

由于前面已经证过不会割药与药材的连边,因此这种边略过不提。

对于割掉一条从源点向药的连边,我们考虑到最后要将最小割减去从源点向外连出的边的容量总和,而在这一过程中,这条边的容量就抵消掉了。

因此,割掉一条从源点向药的连边,就相当于不选择这种药

而对于割掉一条从药材连向汇点的连边则恰好相反,表示选择这种药材。

选择的药的数量与药材的数量必定相等

考虑从源点向药连出了\(n\)条边,从药材向汇点连入了\(n\)条边,则显然至少需要割\(n\)条边,且割\(n\)条边一定可行。

而割去\(n\)条边的代价必然可以表示成\(n*INF+x\),其中\(x\)为某个未知值。

由于割小于\(n\)条边不可行,而割大于\(n\)条边时代价可以表示为\(n'*INF+y\),其中\(n'>n\),\(y\)为某个未知值。

将两式相减得到:

\[(n*INF+x)-(n'*INF+y)=(n-n')*INF+x-y
\]

由于\(INF\)是个很大的数,所以上述式子必然小于\(0\),因此若要求最小割,割去的边数不可能大于\(n\)。(这也是我们要把每条边的权值设成\(INF\)级别的原因)

综上所述,割去的边数必然为\(n\)。

又由于前面证过的连接药与药材的边绝不会被选作最小割中的边,所以这\(n\)条边必然由\(t\)条从源点向药的连边和\(n-t\)条从药材向汇点的连边组成。

再考虑割去一条边的实际意义,也就是说不选择的药的数量选择的药材的数量相加为\(n\)。

显然不选择的药的数量选择的药的数量相加也为\(n\)。

也就是说选择的药的数量与选择的药材的数量必定相等,性质得证。

以此方法能够得到合法答案

考虑前面已经证明过割去的边为\(t\)条从源点向药的连边和\(n-t\)条从药材向汇点的连边。

则代价可以表示为\(n*INF\)减去若干种药的权值。

而从源点向外连出的边的容量总和为\(n*INF\)减去所有药的权值和。

用代价减去容量总和,\(n*INF\)抵消,而代价中减去的那些药的权值与容量总和中这部分权值抵消(前面提到过割去一条从源点向药的连边表示不选这种药),剩下的权值负负得正成为其原本的权值。

然后求和即为答案。

以此方法选出的答案必为最优解

这是一个比较显然的性质。

我们求的是最小割,而最后答案是最小割减去容量总和。

既然是最小割,求的肯定是最小解,而答案就是最优解了。

代码

  1. #include<bits/stdc++.h>
  2. #define Tp template<typename Ty>
  3. #define Ts template<typename Ty,typename... Ar>
  4. #define Reg register
  5. #define RI Reg int
  6. #define Con const
  7. #define CI Con int&
  8. #define I inline
  9. #define W while
  10. #define N 300
  11. #define INF (int)1e9
  12. #define LL long long
  13. using namespace std;
  14. int n;
  15. class FastIO
  16. {
  17. private:
  18. #define FS 100000
  19. #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
  20. #define tn (x<<3)+(x<<1)
  21. #define D isdigit(c=tc())
  22. int f;char c,*A,*B,FI[FS];
  23. public:
  24. I FastIO() {A=B=FI;}
  25. Tp I void read(Ty& x) {x=0,f=1;W(!D) f=c^'-'?1:-1;W(x=tn+(c&15),D);x*=f;}
  26. Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
  27. }F;
  28. class MaxFlow//最大流
  29. {
  30. private:
  31. #define Psz (N<<1)+2
  32. #define Lsz (N*N<<1)+(N<<2)
  33. #define add(x,y,c) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].Cap=c)
  34. LL Ctot;int ee,lnk[Psz+5],cur[Psz+5],q[Psz+5],dep[Psz+5];
  35. struct edge {int to,nxt,Cap;}e[Lsz+5];
  36. I bool BFS()//BFS找增广路
  37. {
  38. RI i,k,H=1,T=1;memset(dep,0,sizeof(dep)),dep[q[1]=s]=1;W(H<=T&&!dep[t])
  39. for(i=lnk[k=q[H++]];i;i=e[i].nxt) e[i].Cap&&!dep[e[i].to]&&(dep[q[++T]=e[i].to]=dep[k]+1);
  40. return dep[t]?(memcpy(cur,lnk,sizeof(lnk)),true):false;
  41. }
  42. I int DFS(CI x,RI f)//DFS统计流量
  43. {
  44. if(!(x^t)||!f) return f;RI i,p,res=0;
  45. for(i=cur[x];i;i=e[i].nxt)
  46. {
  47. if(cur[x]=i,(dep[x]+1)^dep[e[i].to]||!(p=DFS(e[i].to,min(f,e[i].Cap)))) continue;
  48. if(e[i].Cap-=p,e[((i-1)^1)+1].Cap+=p,res+=p,!(f-=p)) break;
  49. }return !res&&(dep[x]=-1),res;
  50. }
  51. public:
  52. int s,t;I MaxFlow() {s=1,t=2;}
  53. I int P1(CI x) {return x+2;}I int P2(CI x) {return x+n+2;}
  54. I void Add(CI x,CI y,CI c) {add(x,y,c),add(y,x,0),Ctot+=c;}
  55. I LL GetAns() {Reg LL t=0;W(BFS()) t+=DFS(s,2*INF);return t;}
  56. }M;
  57. int main()
  58. {
  59. RI i,x,y;Reg LL sum=0;for(F.read(n),i=1;i<=n;++i) for(F.read(x);x;--x) F.read(y),M.Add(M.P1(i),M.P2(y),INF);//建边
  60. for(i=1;i<=n;++i) F.read(x),M.Add(M.s,M.P1(i),INF-x),M.Add(M.P2(i),M.t,INF),sum+=INF-x;//建边
  61. return printf("%lld",M.GetAns()-sum),0;
  62. }

【LOJ6045】「雅礼集训 2017 Day8」价(网络流)的更多相关文章

  1. loj6045 「雅礼集训 2017 Day8」价

    我们考虑最小割. 我一开始觉得是裸的最小割,就直接S到每个减肥药连up+p[i]的边,减肥药到药材连inf边,药材到T连up,然后得到了40分的好成绩. 之后我发现这是一个假的最小割,最小割割的是代价 ...

  2. LOJ_6045_「雅礼集训 2017 Day8」价 _最小割

    LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...

  3. 【LYOI 212】「雅礼集训 2017 Day8」价(二分匹配+最大权闭合子图)

    「雅礼集训 2017 Day8」价 内存限制: 512 MiB时间限制: 1000 ms 输入文件: z.in输出文件: z.out   [分析] 蛤?一开始看错题了,但是也没有改,因为不会做. 一开 ...

  4. 【思维题 最大权闭合子图】loj#6045. 「雅礼集训 2017 Day8」价

    又是经典模型的好题目 题目描述 人类智慧之神 zhangzj 最近有点胖,所以要减肥,他买了 NN 种减肥药,发现每种减肥药使用了若干种药材,总共正好有 NN 种不同的药材. 经过他的人脑实验,他发现 ...

  5. LOJ#6045. 「雅礼集训 2017 Day8」价(最小割)

    题面 传送门 题解 首先先把所有权值取个相反数来求最大收益,因为最小收益很奇怪 然后建图如下:\(S\to\)药,容量\(\inf+p_i\),药\(\to\)药材,容量\(\inf\),药材\(\t ...

  6. loj #6046. 「雅礼集训 2017 Day8」爷

    #6046. 「雅礼集训 2017 Day8」爷 题目描述 如果你对山口丁和 G&P 没有兴趣,可以无视题目背景,因为你估计看不懂 …… 在第 63 回战车道全国高中生大赛中,军神西住美穗带领 ...

  7. [LOJ#6044]. 「雅礼集训 2017 Day8」共[二分图、prufer序列]

    题意 题目链接 分析 钦定 \(k\) 个点作为深度为奇数的点,有 \(\binom{n-1}{k-1}\) 种方案. 将树黑白染色,这张完全二分图的生成树的个数就是我们钦定 \(k\) 个点之后合法 ...

  8. LOJ#6046. 「雅礼集训 2017 Day8」爷(分块)

    题面 传送门 题解 转化为\(dfs\)序之后就变成一个区间加,区间查询\(k\)小值的问题了,这显然只能分块了 然而我们分块之后需要在块内排序,然后二分\(k\)小值并在块内二分小于它的元素--一个 ...

  9. LOJ#6044. 「雅礼集训 2017 Day8」共(Prufer序列)

    题面 传送门 题解 答案就是\(S(n-k,k)\times {n-1\choose k-1}\) 其中\(S(n,m)\)表示左边\(n\)个点,右边\(m\)个点的完全二分图的生成树个数,它的值为 ...

随机推荐

  1. 事物及exec

    事物3要出不多讲: 1.BEGIN TRANSACTION--开启事务 2.COMMIT TRANSACTION--事务执行 3.ROLLBACK TRANSACTION--事务回滚 俩总捕捉事物的方 ...

  2. Ubuntu14.04配置python接口,测试的小问题

    当遇到“ImportError:No module named google.protobuf.internal”(import enum_type_wrapper)的问题时候 solution: P ...

  3. JS你可能还不知道的一些知识点(一)

    js程序是用Unicode字符集编写的, 2.转义字符:反斜线 1 2 3 4 function Test(){   var s='you\'re right,it can\'t be a quote ...

  4. Python镜像源

    镜像源 官方:https://pypi.python.org/pypi 豆瓣:https://pypi.doubanio.com/simple/ 阿里:http://mirrors.aliyun.co ...

  5. MAYA删除不干净

    AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...

  6. pat1045. Favorite Color Stripe (30)

    1045. Favorite Color Stripe (30) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...

  7. Andrew Ng 的 Machine Learning 课程学习 (week3) Logistic Regression

    这学期一直在跟进 Coursera上的 Machina Learning 公开课, 老师Andrew Ng是coursera的创始人之一,Machine Learning方面的大牛.这门课程对想要了解 ...

  8. SQL DATEDIFF语法及时间函数 Sql 查询当天、本周、本月记录

    SQL DATEDIFF语法及时间函数 Sql 查询当天.本周.本月记录 转:http://blog.csdn.net/Json1204/article/details/7863801?locatio ...

  9. autofac 一个接口多个实现的顺序执行

    接口: namespace AutofacTest.Interface { public interface IUserInfo { string GetUserINfo(int uid); int ...

  10. 常规项目用到的jar包之maven的pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...