codeforces103E Buying Sets
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:codeforces103E
正解:网络流+最小权闭合图
解题报告:
考虑这道题的模型。
首先因为存在完备匹配,所以可以给每个点找一个匹配点,然后这个点向所需要的药材的匹配点连边。
然后我们可以得到一个选择一个点就要选择它的所有出边的最小闭合权子图的模型,取个负号跑最大权闭合子图就好了,直接套板子。
这样建图的正确性可以意会一下,很明显可以起到选一个就选另一个的效果。
补一发最大权闭合子图的理解:
很久以前学过但是忘得差不多了。
这类题的模型就是一个每个点带权的有向图,选择了一个点就要选择他的所有出边,最大化选出的点的最大权值和。
建图的方法就是$S$向正权点连容量为点权的边,原图的边容量为$inf$,负权点向$T$连容量为点权的绝对值的边。
先默认选择所有的正权点,$ans$的初值就是正权点的点权之和,而实际情况下可能有些正权点不选,还要另选择一些负权点。
那么$ans=ans-$(不选择正权$+$选择的负权的绝对值),后者就是图的最小割,也就是最大流。
考虑最小割只能与$S$或$T$相连。
与$S$相连的点说明供应$<=$出边流量,那么显然是不选择的正权,因为选了不划算;
与$T$相连的说明,为其提供流量的边还未满,那么这个负权就是选择了正权之后付出的一些负权点代价,显然会划算。
//It is made by ljh2000
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <queue>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long LL;
const int MAXN = 15001;
const int inf = (1<<29);
int n,P[MAXN],Tim,match[MAXN],vis[MAXN];
vector<int>medi[MAXN];
LL ans; inline int getint(){
int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
} namespace network{
const int MAXM = 1000011;
int ecnt,first[MAXN],S,T,dui[MAXN],deep[MAXN];
queue<int>q;
struct edge{ int to,f,next; }e[MAXM];
inline void Init(){ ecnt=1; S=n+1; T=S+1; }
inline void link(int x,int y,int z){
e[++ecnt].next=first[x]; first[x]=ecnt; e[ecnt].to=y; e[ecnt].f=z;
e[++ecnt].next=first[y]; first[y]=ecnt; e[ecnt].to=x; e[ecnt].f=0;
} inline bool bfs(){
for(int i=1;i<=T;i++) deep[i]=-1; deep[S]=0; q.push(S); int u;
while(!q.empty()){
u=q.front(); q.pop();
for(int i=first[u];i;i=e[i].next) {
if(e[i].f==0) continue;
int v=e[i].to; if(deep[v]!=-1) continue;
deep[v]=deep[u]+1; q.push(v);
}
}
return (deep[T]!=-1);
} inline int dinic(int x,int remain){
if(x==T || remain==0) return remain;
int f,flow=0;
for(int i=first[x];i;i=e[i].next) {
if(e[i].f==0) continue;
int v=e[i].to; if(deep[v]!=deep[x]+1) continue;
f=dinic(v,min(remain,e[i].f));
if(f==0) deep[v]=-1;
else {
flow+=f; remain-=f;
e[i].f-=f; e[i^1].f+=f;
if(remain==0) return flow;
}
}
return flow;
}
} inline bool dfs(int x){
if(vis[x]==Tim/*!!!*/) return false;//!!!
vis[x]=Tim;
for(int i=0,ss=medi[x].size();i<ss;i++) {
int v=medi[x][i]; if(vis[v]==Tim) continue;
if(!match[v] || dfs(match[v])) {
match[v]=x;
return true;
}
}
return false;
} inline void work(){
using namespace network;
n=getint(); Init(); int x,y;
for(int i=1;i<=n;i++) { x=getint(); while(x--) { y=getint(); medi[i].push_back(y+n); } }
for(int i=1;i<=n;i++) Tim++,dfs(i);
for(int i=1;i<=n;i++) P[i]=getint();
for(int i=1;i<=n;i++) for(int j=0,ss=medi[i].size();j<ss;j++) link(i,match[ medi[i][j] ],inf);
for(int i=1;i<=n;i++) {
P[i]=-P[i];
if(P[i]>0) link(S,i,P[i]),ans+=P[i];
else link(i,T,-P[i]);
} while(bfs())
ans-=dinic(S,inf); ans=-ans;
printf("%I64d",ans);
} int main()
{
#ifndef ONLINE_JUDGE
freopen("103.in","r",stdin);
freopen("103.out","w",stdout);
#endif
work();
return 0;
}
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
codeforces103E Buying Sets的更多相关文章
- CF 103E Buying Sets 最大权闭合子图,匹配 难度:4
http://codeforces.com/problemset/problem/103/E 这道题首先一看就很像是最大权闭合子图,但是我们可以认为现在有两种点,数字和集合点,我们需要消除数字点的影响 ...
- 【codeforces 103E】 Buying Sets
http://codeforces.com/problemset/problem/103/E (题目链接) 题意 给出$n$个数,每个数与一个集合相关联.从其中选出最小的若干个数,选出的数的个数与这些 ...
- TSQL 分组集(Grouping Sets)
分组集(Grouping Sets)是多个分组的并集,用于在一个查询中,按照不同的分组列对集合进行聚合运算,等价于对单个分组使用“union all”,计算多个结果集的并集.使用分组集的聚合查询,返回 ...
- grouping sets从属子句的运用
grouping sets主要是用来合并多个分组的结果. 对于员工目标业绩表'businessTarget': employeeId targetDate idealDistAmount 如果需要分别 ...
- Codeforces 722D. Generating Sets
D. Generating Sets time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- 【转】rollup、cub、grouping sets、grouping、grouping_id在报表中的应用
摘自 http://blog.itpub.net/26977915/viewspace-734114/ 在报表语句中经常要使用各种分组汇总,rollup和cube就是常用的分组汇总方式. 第一:gro ...
- salesforce 零基础学习(十九)Permission sets 讲解及设置
Permission sets以及Profile是常见的设置访问权限的方式. Profile规则为'who see what'.通过Profile可以将一类的用户设置相同的访问权限.对于有着相同Pro ...
- Python数据类型之“集合(Sets)与映射(Mapping)”
一.集合类型(Sets) 集合对象是不同的(不可重复)hashable对象的无序集合.常见用法包括:成员关系测试.移除序列中的重复.以及科学计算,例如交集.并集.差分和对称差分.通俗点来说,集合是一个 ...
- 【Swift学习】Swift编程之旅---集合类型之Sets(七)
Sets是存储无序的相同类型的值,你可以在顺序不重要的情况下使用Sets来替代数组,或者当你需要同一个值在集合中只出现一次时. 一.Sets类型语法 写作Set<Element>,Ele ...
随机推荐
- Python中的高级数据结构(转)
add by zhj: Python中的高级数据结构 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数 ...
- bat脚本运行py文件失败(一闪而过)
简单记录下问题及原因,方便回顾. 问题 通过 bat 脚本运行 py 文件时,终端一闪而过,没能成功运行. 查证后发现问题出在编码上: 首先检查下bat文件编码格式(推荐 notepad++ ) 打开 ...
- mdf, ldf文件导入到sql server 2005的方法
mdf, ldf文件导入到sql server 2005的方法 在实际的工作中, 有很多涉及到数据库资料的备份,转移, 恢复等方面的工作, 但是并不是所有的资料都是以.bak格式存在的, 比如说, 你 ...
- nginx 413 request entity too large解决办法
nginx 出现:413 request entity too large,一般是在上传图片的时候,上传的图片大小超过了服务器设置的最大上传大小,需要修改nginx和PHP的设置: (1)打开 /us ...
- 关于理财和买房 http://shouce.jb51.net/phpcms/ https://www.bj.cmbchina.com/bjtransweb/wsgzd_employ/login.jsp
对于绝大多数家境普通的年轻人来说,青年阶段无疑是一生中手头最紧的时候.原因很简单,这个阶段花钱最多,挣钱却最少.年轻人收入往往是硬性的低,开支却往往是硬性 的高.已经加班到晕头转向的小职员,很难再 ...
- JAVA与ACM
这两天学了一下JAVA的语法,还没有学习后面的核心地方,突然间觉得JAVA这门语言很棒,我要在接下来的时间系统的学习一下.就这么愉快地决定了. Java对于大数计算这方面的优势很大.最重要的是代码量小 ...
- vultr服务器上搭建PHP运行环境-centos7
安装nginx: yum install nginx 开启Nginx systemctl start nginx 访问你的域名或者ip 例如:quantaedu.com 安装PHP 查看系统版本lsb ...
- (转)spring mvc forward与redirect
forward 转发,如return "forward:/hello"; 浏览器的地址栏不会变,但是有视图返回来 redirect 重定向,如return "redire ...
- docker——安装
Docker划分为CE和EE.CE即社区版(免费,支持后期三个月),EE即企业版,强调安全,付费使用. #安装依赖包 yum install -y yum-utils device-mapper-pe ...
- filebeat+logstash通过zabbix微信报警
一.安装软件: 1.在要收集日志的机器上安装filebeat: 1).下载安装: cd /usr/local/src wget https://artifacts.elastic.co/downloa ...