Magic Potion(最大流,跑两遍网络流或者加一个中转点)
Magic Potion

从源点到英雄分别拉容量为1和2的边,跑两遍网络流,判断两次的大小和k的大小
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<set> #define maxn 500005
#define MAXN 500005
#define mem(a,b) memset(a,b,sizeof(a))
const int N=;
const int M=;
const int INF=0x3f3f3f3f;
using namespace std;
int n;
struct Edge{
int v,next;
int cap,flow;
}edge[MAXN*];//注意这里要开的够大。。不然WA在这里真的想骂人。。问题是还不报RE。。
int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
int cnt=;//实际存储总边数
void isap_init()
{
cnt=;
memset(pre,-,sizeof(pre));
}
void isap_add(int u,int v,int w)//加边
{
edge[cnt].v=v;
edge[cnt].cap=w;
edge[cnt].flow=;
edge[cnt].next=pre[u];
pre[u]=cnt++;
}
void add(int u,int v,int w){
isap_add(u,v,w);
isap_add(v,u,);
}
bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里,但是好像是时间要长
{
memset(dep,-,sizeof(dep));
memset(gap,,sizeof(gap));
gap[]=;
dep[t]=;
queue<int>q;
while(!q.empty())
q.pop();
q.push(t);//从汇点开始反向建层次图
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=pre[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
if(dep[v]==-&&edge[i^].cap>edge[i^].flow)//注意是从汇点反向bfs,但应该判断正向弧的余量
{
dep[v]=dep[u]+;
gap[dep[v]]++;
q.push(v);
//if(v==sp)//感觉这两句优化加了一般没错,但是有的题可能会错,所以还是注释出来,到时候视情况而定
//break;
}
}
}
return dep[s]!=-;
}
int isap(int s,int t)
{
if(!bfs(s,t))
return ;
memcpy(cur,pre,sizeof(pre));
//for(int i=1;i<=n;i++)
//cout<<"cur "<<cur[i]<<endl;
int u=s;
path[u]=-;
int ans=;
while(dep[s]<n)//迭代寻找增广路,n为节点数
{
if(u==t)
{
int f=INF;
for(int i=path[u];i!=-;i=path[edge[i^].v])//修改找到的增广路
f=min(f,edge[i].cap-edge[i].flow);
for(int i=path[u];i!=-;i=path[edge[i^].v])
{
edge[i].flow+=f;
edge[i^].flow-=f;
}
ans+=f;
u=s;
continue;
}
bool flag=false;
int v;
for(int i=cur[u];i!=-;i=edge[i].next)
{
v=edge[i].v;
if(dep[v]+==dep[u]&&edge[i].cap-edge[i].flow)
{
cur[u]=path[v]=i;//当前弧优化
flag=true;
break;
}
}
if(flag)
{
u=v;
continue;
}
int x=n;
if(!(--gap[dep[u]]))return ans;//gap优化
for(int i=pre[u];i!=-;i=edge[i].next)
{
if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x)
{
x=dep[edge[i].v];
cur[u]=i;//常数优化
}
}
dep[u]=x+;
gap[dep[u]]++;
if(u!=s)//当前点没有增广路则后退一个点
u=edge[path[u]^].v;
}
return ans;
} struct sair{
int num;
int mp[];
}mp[]; int main(){
std::ios::sync_with_stdio(false);
int m,s,t,k;
cin>>n>>m>>k;
int a,b,c;
isap_init();
s=,t=n+m+;
for(int i=;i<=n;i++) add(s,i,);
for(int i=;i<=n;i++){
cin>>mp[i].num;
for(int j=;j<=mp[i].num;j++){
cin>>mp[i].mp[j];
add(i,n+mp[i].mp[j],);
}
}
for(int i=;i<=m;i++) add(n+i,t,);
int tmp=n;
n=t+;
int ans1=isap(s,t); n=tmp;
isap_init();
for(int i=;i<=n;i++) add(s,i,);
for(int i=;i<=n;i++){
for(int j=;j<=mp[i].num;j++){
add(i,n+mp[i].mp[j],);
}
}
for(int i=;i<=m;i++) add(n+i,t,);
tmp=n;
n=t+;
int ans2=isap(s,t);
if(ans2-ans1<=k){
cout<<ans2<<endl;
}
else{
cout<<ans1+k<<endl;
}
}
源点连英雄容量为1,英雄连怪物容量为1,怪物连汇点容量为1
源点连中转点容量为k,中转点连英雄容量为1
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<set> #define maxn 500005
#define MAXN 500005
#define mem(a,b) memset(a,b,sizeof(a))
const int N=;
const int M=;
const int INF=0x3f3f3f3f;
using namespace std;
int n;
struct Edge{
int v,next;
int cap,flow;
}edge[MAXN*];//注意这里要开的够大。。不然WA在这里真的想骂人。。问题是还不报RE。。
int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
int cnt=;//实际存储总边数
void isap_init()
{
cnt=;
memset(pre,-,sizeof(pre));
}
void isap_add(int u,int v,int w)//加边
{
edge[cnt].v=v;
edge[cnt].cap=w;
edge[cnt].flow=;
edge[cnt].next=pre[u];
pre[u]=cnt++;
}
void add(int u,int v,int w){
isap_add(u,v,w);
isap_add(v,u,);
}
bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里,但是好像是时间要长
{
memset(dep,-,sizeof(dep));
memset(gap,,sizeof(gap));
gap[]=;
dep[t]=;
queue<int>q;
while(!q.empty())
q.pop();
q.push(t);//从汇点开始反向建层次图
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=pre[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
if(dep[v]==-&&edge[i^].cap>edge[i^].flow)//注意是从汇点反向bfs,但应该判断正向弧的余量
{
dep[v]=dep[u]+;
gap[dep[v]]++;
q.push(v);
//if(v==sp)//感觉这两句优化加了一般没错,但是有的题可能会错,所以还是注释出来,到时候视情况而定
//break;
}
}
}
return dep[s]!=-;
}
int isap(int s,int t)
{
if(!bfs(s,t))
return ;
memcpy(cur,pre,sizeof(pre));
//for(int i=1;i<=n;i++)
//cout<<"cur "<<cur[i]<<endl;
int u=s;
path[u]=-;
int ans=;
while(dep[s]<=n)//迭代寻找增广路,n为节点数
{
if(u==t)
{
int f=INF;
for(int i=path[u];i!=-;i=path[edge[i^].v])//修改找到的增广路
f=min(f,edge[i].cap-edge[i].flow);
for(int i=path[u];i!=-;i=path[edge[i^].v])
{
edge[i].flow+=f;
edge[i^].flow-=f;
}
ans+=f;
u=s;
continue;
}
bool flag=false;
int v;
for(int i=cur[u];i!=-;i=edge[i].next)
{
v=edge[i].v;
if(dep[v]+==dep[u]&&edge[i].cap-edge[i].flow)
{
cur[u]=path[v]=i;//当前弧优化
flag=true;
break;
}
}
if(flag)
{
u=v;
continue;
}
int x=n;
if(!(--gap[dep[u]]))return ans;//gap优化
for(int i=pre[u];i!=-;i=edge[i].next)
{
if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x)
{
x=dep[edge[i].v];
cur[u]=i;//常数优化
}
}
dep[u]=x+;
gap[dep[u]]++;
if(u!=s)//当前点没有增广路则后退一个点
u=edge[path[u]^].v;
}
return ans;
} struct sair{
int num;
int mp[];
}mp[]; int main(){
std::ios::sync_with_stdio(false);
int m,s,t,k;
cin>>n>>m>>k;
int a,b,c;
isap_init();
s=,t=n+m+;
int ck=t+;
for(int i=;i<=n;i++)
add(s,i,);
add(s,ck,k);
for(int i=;i<=n;i++){
cin>>a;
for(int j=;j<=a;j++){
cin>>b;
add(i,n+b,);
}
}
for(int i=;i<=m;i++)
add(n+i,t,);
for(int i=;i<=n;i++){
add(ck,i,);
}
int tmp=n;
n=ck+;
int ans=isap(s,t);
cout<<ans<<endl;
}
Magic Potion(最大流,跑两遍网络流或者加一个中转点)的更多相关文章
- Gym 101981I - Magic Potion - [最大流][2018-2019 ACM-ICPC Asia Nanjing Regional Contest Problem I]
题目链接:http://codeforces.com/gym/101981/attachments There are n heroes and m monsters living in an isl ...
- 洛谷P1073最优贸易(跑两遍dij)
题目描述 CC C国有n n n个大城市和m mm 条道路,每条道路连接这 nnn个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 mmm 条道路中有一部分为单向通行的道路,一部分为 ...
- Gym - 101981I The 2018 ICPC Asia Nanjing Regional Contest I.Magic Potion 最大流
题面 题意:n个英雄,m个怪兽,第i个英雄可以打第i个集合里的一个怪兽,一个怪兽可以在多个集合里,有k瓶药水,每个英雄最多喝一次,可以多打一只怪兽,求最多打多少只 n,m,k<=500 题解:显 ...
- POJ3268 Silver Cow Party (建反图跑两遍Dij)
One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big co ...
- 2018icpc南京现场赛-I Magic Potion(最大流)
题意: n个英雄,m个怪兽,第i个英雄可以打第i个集合里的怪兽,一个怪兽可以在多个集合里 有k瓶药水,每个英雄最多喝一次,可以多打一只怪兽,求最多打多少只 n,m,k<=500 思路: 最大流, ...
- HDU2612 Find a way (跑两遍BFS)
Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. Leave Ningbo one year ...
- [Cqoi2014]危桥 (两遍网络流)
题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { , ...
- Gym101981I Magic Potion(最大流)
Problem I. Magic Potion There are n heroes and m monsters living in an island. The monsters became v ...
- map集合修改其中元素 去除Map集合中所有具有相同值的元素 Properties长久保存的流操作 两种用map记录单词或字母个数的方法
package com.swift.lianxi; import java.util.HashMap; import java.util.Iterator; import java.util.Map; ...
随机推荐
- Sqlserver 按照时间段统计数据
WITH t1 ( [hour], title ) , ' 0:00:00--- 1:00:00' UNION ALL , ' 1:00:00--- 2:00:00' UNION ALL , ' 2: ...
- Loj 2005 相关分析
Loj 2005 相关分析 大力把式子拆开. \[ \begin{aligned} a &= \frac {\sum_{i=L}^{R} (x_i-\bar{x})(y_i-\bar{y})} ...
- 设计模式(Python)-简单工厂,工厂方法和抽象工厂模式
本系列文章是希望将软件项目中最常见的设计模式用通俗易懂的语言来讲解清楚,并通过Python来实现,每个设计模式都是围绕如下三个问题: 为什么?即为什么要使用这个设计模式,在使用这个模式之前存在什么样的 ...
- Documentation/filesystems/sysfs.txt 文档翻译--sysfs
sysfs - 用于导出内核对象的文件系统. 1.sysfs是一个基于ram的文件系统,最初基于ramfs. 它提供了一种方法,可以将内核数据结构,它们的属性以及它们之间的链接导出到用户空间.sysf ...
- streamsets record header 属性
record 的header 属性可以在pipeline 逻辑中使用. 有写stages 会为了特殊目录创建reord header 属性,比如(cdc)需要进行crud 操作类型的区分 你可以使用一 ...
- IT项目管理的十六个字心得体会
目标驱动,系统思维,风险意识,数据量化 凡事预则立,不预则废.如果你不知道要到哪里?给你一张地图也没有用.目标驱动首先要有最基本的计划管理和时间管理能力.对于一个项目,我们过程中做的所有工作都是为了要 ...
- npm查看全局安装过的包
在使用node的时候,用npm安装了很多软件,过一段时间没有使用就会忘记,怎么查看自己全局安装过的包,用命令 npm list -g --depth 0 在百度里搜不到结果的,我在google里老外的 ...
- 【linux】centos6.5搭建svn
1.检查是否已安装 rpm -qa subversion 如果要卸载旧版本: yum remove subversion 2.安装 yum install subversion PS:yum inst ...
- Java利用ScriptEngineManager对计算公式的支持
1.ScriptEngineManager是JDK6提出的相关方法,这方式的主要目的就是用来对脚本语言的处理.这里只是简单介绍一下对我们常用的数学公式的应用. 2.ScriptEngineManage ...
- MySQL单机单实例安装脚本
说明:使用mysql generic tar.gz包快速安装mysql 三个文件installation_of_single_mysql.sh.template_install-my.cnf.mysq ...