【LYOI 212】「雅礼集训 2017 Day8」价(二分匹配+最大权闭合子图)
「雅礼集训 2017 Day8」价
内存限制: 512 MiB时间限制: 1000 ms输入文件: z.in输出文件: z.out
【分析】
蛤?一开始看错题了,但是也没有改,因为不会做。
一开始以为是并集全等,其实只是集合内元素个数相等。
如果是一开始的题意的话,就是选了什么药材就要选什么药,明显的一个最大权闭合子图【于是我真的就这样打了,加上暴力还搞了很多分
数量一样的话,男神有一个方法就是放大点权,普通选法的话左边比右边少,所以药的点权+INF,药材的点权-INF,然后做最大权闭合子图【我对此只能膜膜膜
然后题目有一个条件就是要完美匹配。
正解是先做一遍完美匹配,然后药材选了,他的匹配点的药也要选。
证明:
1、可行解一定是这样的。
假设有一个可行解,左右大小都是i,因为左边选的,它的连边的右边一定选,所以i条匹配边一定在集合里面。所以药材的点的匹配边一定在集合里面。
2、这样做出来的答案一定左右大小相等
若左边大于右边,左边一定有一个点的匹配边在集合外,与左边的点的连边的点都选矛盾。
若左边小于右边,右边一定有一个点选了,但是没有选它的匹配点,与你的做法矛盾。
就是这样证明吧?
其实虽然我不会推出结论,但是这题的key的位置实在太明显了,脑洞再大一点就好了。毕竟这种题是证明还好,但是比较难以直接想到结论的。
- #include<cstdio>
- #include<cstdlib>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<queue>
- using namespace std;
- #define Maxn 310
- #define INF 0xfffffff
- // #define LL long long
- int mymin(int x,int y) {return x<y?x:y;}
- int n;
- struct node
- {
- int x,y,next,f,o;
- }t[Maxn*Maxn*];
- int first[Maxn],len;
- void ins(int x,int y,int f)
- {
- if(x==y) return;
- t[++len].x=x;t[len].y=y;t[len].f=f;
- t[len].next=first[x];first[x]=len;t[len].o=len+;
- t[++len].x=y;t[len].y=x;t[len].f=;
- t[len].next=first[y];first[y]=len;t[len].o=len-;
- }
- queue<int > q;
- int dis[Maxn],st,ed;
- bool bfs()
- {
- while(!q.empty()) q.pop();
- memset(dis,-,sizeof(dis));
- q.push(st);dis[st]=;
- while(!q.empty())
- {
- int x=q.front();
- for(int i=first[x];i;i=t[i].next) if(t[i].f>)
- {
- int y=t[i].y;
- if(dis[y]==-)
- {
- dis[y]=dis[x]+;
- q.push(y);
- }
- }
- q.pop();
- }
- return dis[ed]!=-;
- }
- int ffind(int x,int flow)
- {
- if(x==ed) return flow;
- int now=;
- for(int i=first[x];i;i=t[i].next) if(t[i].f>)
- {
- int y=t[i].y;
- if(dis[y]==dis[x]+)
- {
- int a=ffind(y,mymin(flow-now,t[i].f));
- t[i].f-=a;
- t[t[i].o].f+=a;
- now+=a;
- }
- if(now==flow) break;
- }
- if(now==) dis[x]=-;
- return now;
- }
- int ans=;
- void max_flow()
- {
- while(bfs())
- {
- ans-=ffind(st,INF);
- }
- }
- void output()
- {
- for(int i=;i<=len;i+=)
- {
- printf("%d -> %d %d\n",t[i].x,t[i].y,t[i].f);
- }
- }
- //-------------------------
- int match[Maxn],chw[Maxn],g[Maxn][Maxn];
- bool ffind2(int x,int nt)
- {
- for(int i=;i<=g[x][];i++)
- {
- int y=g[x][i];
- if(chw[y]!=nt)
- {
- chw[y]=nt;
- if(!match[y]||ffind2(match[y],nt))
- {
- match[y]=x;
- return ;
- }
- }
- }
- return ;
- }
- void get_match()
- {
- memset(chw,,sizeof(chw));
- memset(match,,sizeof(match));
- int nt=;
- for(int i=;i<=n;i++)
- {
- ffind2(i,++nt);
- }
- }
- //-------------------------
- int main()
- {
- scanf("%d",&n);
- st=n+;ed=st+;
- bool ok=;int sm=;
- for(int i=;i<=n;i++)
- {
- int x;
- scanf("%d",&x);
- g[i][]=x;
- for(int j=;j<=x;j++)
- {
- int y;
- scanf("%d",&y);
- g[i][j]=y;
- // ins(i,y,INF);
- }
- }
- get_match();
- // for(int i=1;i<=n;i++) printf("%d ",match[i]);printf("\n");
- for(int i=;i<=n;i++)
- for(int j=;j<=g[i][];j++)
- {
- ins(i,match[g[i][j]],INF);
- }
- for(int i=;i<=n;i++)
- {
- int w;
- scanf("%d",&w);
- w=-w;
- if(w>) {ans+=w;ins(st,i,w);}
- else ins(i,ed,-w);
- }
- // output();
- max_flow();
- printf("%d\n",-ans);
- return ;
- }
2017-04-09 21:36:14
【LYOI 212】「雅礼集训 2017 Day8」价(二分匹配+最大权闭合子图)的更多相关文章
- LOJ_6045_「雅礼集训 2017 Day8」价 _最小割
LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...
- loj6045 「雅礼集训 2017 Day8」价
我们考虑最小割. 我一开始觉得是裸的最小割,就直接S到每个减肥药连up+p[i]的边,减肥药到药材连inf边,药材到T连up,然后得到了40分的好成绩. 之后我发现这是一个假的最小割,最小割割的是代价 ...
- LOJ#6045. 「雅礼集训 2017 Day8」价(最小割)
题面 传送门 题解 首先先把所有权值取个相反数来求最大收益,因为最小收益很奇怪 然后建图如下:\(S\to\)药,容量\(\inf+p_i\),药\(\to\)药材,容量\(\inf\),药材\(\t ...
- 【LOJ6045】「雅礼集训 2017 Day8」价(网络流)
点此看题面 大致题意: 有\(n\)种药,每种药有一个权值,且使用了若干种药材.让你选择若干种药,使得药的数量与所使用的药材并集大小相等,求最小权值总和. 网络流 \(hl666\):这种数据范围,一 ...
- 【思维题 最大权闭合子图】loj#6045. 「雅礼集训 2017 Day8」价
又是经典模型的好题目 题目描述 人类智慧之神 zhangzj 最近有点胖,所以要减肥,他买了 NN 种减肥药,发现每种减肥药使用了若干种药材,总共正好有 NN 种不同的药材. 经过他的人脑实验,他发现 ...
- loj #6046. 「雅礼集训 2017 Day8」爷
#6046. 「雅礼集训 2017 Day8」爷 题目描述 如果你对山口丁和 G&P 没有兴趣,可以无视题目背景,因为你估计看不懂 …… 在第 63 回战车道全国高中生大赛中,军神西住美穗带领 ...
- [LOJ#6044]. 「雅礼集训 2017 Day8」共[二分图、prufer序列]
题意 题目链接 分析 钦定 \(k\) 个点作为深度为奇数的点,有 \(\binom{n-1}{k-1}\) 种方案. 将树黑白染色,这张完全二分图的生成树的个数就是我们钦定 \(k\) 个点之后合法 ...
- LOJ#6046. 「雅礼集训 2017 Day8」爷(分块)
题面 传送门 题解 转化为\(dfs\)序之后就变成一个区间加,区间查询\(k\)小值的问题了,这显然只能分块了 然而我们分块之后需要在块内排序,然后二分\(k\)小值并在块内二分小于它的元素--一个 ...
- LOJ#6044. 「雅礼集训 2017 Day8」共(Prufer序列)
题面 传送门 题解 答案就是\(S(n-k,k)\times {n-1\choose k-1}\) 其中\(S(n,m)\)表示左边\(n\)个点,右边\(m\)个点的完全二分图的生成树个数,它的值为 ...
随机推荐
- Java实现链式存储的二叉树
二叉树的定义: 二叉树(BinaryTree)是n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的.分别称作这个根的左子树和右子树的二叉树组成. 二叉树的遍历方式主要 ...
- 使用 XSLT 作为 HTML 的样式表
简介 当听到样式表这个词时,您可能会想到 CSS 样式表.XSLT 样式表通常用于 XML 转换,比如在 Web 服务之间映射数据.因为 XSLT 非常适合此用途,所以创建了顶层元素 <styl ...
- HDU 1394 Minimum Inversion Number (树状数组)
题目链接 Problem Description The inversion number of a given number sequence a1, a2, ..., an is the numb ...
- Vue的keep-alive
Vue的keep-alive: 简答的做下理解 缓存!页面从某一个页面跳转到另一个页面的时候,需要进行一定的缓存,然后这个时候调用的钩子函数是actived,而在第一次加载的时候,created.ac ...
- U盘出现大量乱码文件,并且不能彻底删除
问题如图所示: 问题出现原因:不正常的插拔等情况造成的,导致U盘的文件分配表错乱了 解决方法:参考http://bbs.cfanclub.net/thread-405004-1-1.html 运行ch ...
- Codeforces 665E. Beautiful Subarrays (字典树)
题目链接:http://codeforces.com/problemset/problem/665/E (http://www.fjutacm.com/Problem.jsp?pid=2255) 题意 ...
- HMM的概述(五个基本元素、两个假设、三个解决的问题)
一.五个基本元素 HMM是个五元组 λ =( S, O , π ,A,B) S:状态值集合,O:观察值集合,π:初始化概率,A:状态转移概率矩阵,B:给定状态下,观察值概率矩阵 二.两个假设 HM ...
- 使用qt写的简单的图片浏览器
功能特别简单,支持png,jpg,bmp,gif文件,支持自适应窗口大小,支持放大缩小,旋转功能还有点问题,支持上下按键选择图片 因为初学qt,所以很多东西都不太会,而且c++学的不是太好,没有怎么使 ...
- perl6正则 2: 字母,数字,空格,下划线, 字符集
数字, 字母, 下划线 在perl6中, 如果是 数字, 字母, 下划线, 在正则里可以正接写上. > so / True > so 'perl6_' ~~ /_/ True > 非 ...
- 17 - 路径操作-shutil模块
目录 1 路径操作 1.1 os.path模块 1.2 pathlib模块 1.2.1 目录操作 1.2.2 文件操作 1.3 os 模块 2 shutil模块 2.1 copy复制 2.2 rm删除 ...