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 ...
随机推荐
- django-luffycity-购物车接口
一 基本功能 -添加购物车 -详见代码 -修改课程价格策略 -put或者patch {"course_id": "1", "policy_id&qu ...
- Flask蓝图目录、Flask-SQLAlchemy、Flask-Script、Flask-Migrate
一.Flask蓝图目录 我们之前写的Flask项目都是自己组织的目录结构,其实Flask官方有其推荐的目录结构,以下就是一个符合官方推荐的Flask小型应用的项目结构目录示例,如下: 如图,这就是我们 ...
- srs(srs-librtmp推送h264原始数据)
1.下载最新srs源码 https://github.com/ossrs/srs/releases 2.编译(进入~/srs-2.0-r4/trunk目录) ./configure --with-li ...
- oralce 查看执行计划
SQL的执行计划实际代表了目标SQL在Oracle数据库内部的具体执行步骤,作为调优,只有知道了优化器选择的执行计划是否为当前情形下最优的执行计划,才能够知道下一步往什么方向. 执行计划的定义:执行目 ...
- struct初始化
C语言中struct初始化 • 普通结构体的初始化 假设我们有如下的一段代码,其中已有Student结构体,要求实例化一个Student对象并将其初始化. #include <stdio.h&g ...
- PL/SQL 表约束
1. 表相关 a. 主键:constraint [主键的约束名] primary key b. 外键:constraint [外键约束名] foreign key( ) references []() ...
- android线程学习心得
有一篇关于android线程讲的非常好,大家可以参考下,其中有一句话讲的非常好,就拿来做开篇之句: 当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主 ...
- kivy sdl2 - ImportError: DLL load failed: 找不到指定的模块
from kivy.app import App from kivy.uix.button import Button class TestApp(App): def build(self): ret ...
- Django学习笔记之Django ORM相关操作
一般操作 详细请参考官方文档 必知必会13条 <> all(): 查询所有结果 <> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 <> ...
- 通过paramiko模块在远程主机上执行命令
安装paramiko模块 /usr/local/python36/bin/pip3 install paramiko 1.获取cpu使用率 #!/usr/bin/python #coding=utf8 ...