【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\)个点的完全二分图的生成树个数,它的值为 ...
随机推荐
- 遍历hashmap
转]Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml 第一种: Map map = new HashM ...
- 20155117 王震宇 2006-2007-2 《Java程序设计》第四周学习总结
教材学习内容总结 继承(inheritance) 继承是面向对象软件技术当中的一个概念.继承可以使得子类别具有父类别的各种属性和方法,避免了重复的行为定义.在子类别继承父类别的同时,可以重新定义某些属 ...
- 引用类型 ( 对象定义 )——Date 类型
本文地址:http://www.cnblogs.com/veinyin/p/7607743.html 1 创建日期对象 var date = new Date(); 2 可以给日期对象传值 2.1 ...
- CSS实现箭头效果
有时候网页中使用箭头以增强效果,一般的做法是使用图片,今天我们使用CSSCSS来实现“箭头效果”,使用CSS我们必须兼容所有浏览器(IE6.7.8.9.10.+),Chrome,Firefox,Ope ...
- keypress 、keydown、keyup后触发回车
1.keypress .keydown.keyup的区别 keypress表示键盘按下的全过程,只有按下任意字母数字键(后退.删除等系统功能键无效)时才触发,捕获到的keyCode区分大小写 keyd ...
- [006] largest_common_substring
[Description] Given two different strings, find the largest successive common substring. e.g. str1[] ...
- 利用pycharm运行scrapy以及scrapy的配置
1.安装两个whl文件 https://pypi.python.org/pypi/Twisted 下载Twisted的whl文件 https://pypi.python.org/pypi/Scrapy ...
- mac 上使用octave的plot错误的解决办法
在mac10.10上使用octave的时候,键入 plot(x, y)的时候会出现如下错误: ^ line : unknown or ambiguous terminal type; type jus ...
- gdb安装
1.卸载原有gdb 以root用户登录 1.1 查询原有gdb包名,执行命令: rpm -q gdb 1.2 卸载原有gdb包,假设gdb包名为gdb-7.0-0.4.16,执行命令:rpm - ...
- Metro应用Json数据处理
Windows Phone 8 或者 Windows 8 平台对JSON数据的处理方式基本是一致的,需要使用DataContractJsonSerializer类将对象的实例序列化为JSON字符串,并 ...