Magic Potion

http://codeforces.com/gym/101981/attachments/download/7891/20182019-acmicpc-asia-nanjing-regional-contest-en.pdf

从源点到英雄分别拉容量为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(最大流,跑两遍网络流或者加一个中转点)的更多相关文章

  1. 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 ...

  2. 洛谷P1073最优贸易(跑两遍dij)

    题目描述 CC C国有n n n个大城市和m mm 条道路,每条道路连接这 nnn个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 mmm 条道路中有一部分为单向通行的道路,一部分为 ...

  3. Gym - 101981I The 2018 ICPC Asia Nanjing Regional Contest I.Magic Potion 最大流

    题面 题意:n个英雄,m个怪兽,第i个英雄可以打第i个集合里的一个怪兽,一个怪兽可以在多个集合里,有k瓶药水,每个英雄最多喝一次,可以多打一只怪兽,求最多打多少只 n,m,k<=500 题解:显 ...

  4. 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 ...

  5. 2018icpc南京现场赛-I Magic Potion(最大流)

    题意: n个英雄,m个怪兽,第i个英雄可以打第i个集合里的怪兽,一个怪兽可以在多个集合里 有k瓶药水,每个英雄最多喝一次,可以多打一只怪兽,求最多打多少只 n,m,k<=500 思路: 最大流, ...

  6. HDU2612 Find a way (跑两遍BFS)

    Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. Leave Ningbo one year ...

  7. [Cqoi2014]危桥 (两遍网络流)

    题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { , ...

  8. Gym101981I Magic Potion(最大流)

    Problem I. Magic Potion There are n heroes and m monsters living in an island. The monsters became v ...

  9. map集合修改其中元素 去除Map集合中所有具有相同值的元素 Properties长久保存的流操作 两种用map记录单词或字母个数的方法

    package com.swift.lianxi; import java.util.HashMap; import java.util.Iterator; import java.util.Map; ...

随机推荐

  1. Sql 基础问题

    Ref Projection and Selection 联结查询的原理(笛卡尔积) 设计 MySQL 数据表的时候一般都有一列为自增 ID,这样设计原因是什么,有什么好处?

  2. 使用Junit进行Java单元测试

    1.新建一个Number类,该类中包含两个函数,求和.求差 2.在eclipse上安装Junit 右键test工程,选择“Properties”→“Java Build Path”→“Librarie ...

  3. IE、Chrome、Firefox 三大浏览器对比

    1. 代理 IE 浏览器设置代理位置在: [Internet 选项]⇒ [连接]选项卡 ⇒ [局域网设置],如下: Chrome 的代理配置界面完全同 IE,只是你设置路径在: [设置]⇒ [高级]⇒ ...

  4. [笔记]CodeIgniter的SESSION

         由于HTTP协议本身是无状态的,所以当保留某个用户的访问状态信息时,需要客户端有一个唯一标识传给服务端,这个唯一标识就是SESSION ID,存放在客户端的COOKIE中,然后服务端根据该标 ...

  5. leisure time

    终于把论文翻译完了,天哪,现在感觉解脱一般. 这些天看电视,玩游戏,也不止学了写什么,现在调整了下心情,重新确定下目标吧. 最近很想学Python和Qt,哎,技术永远都是学不完了,理解操作系统和组成原 ...

  6. Ext.js 之MVC

    Ext.js 4.0之MVC

  7. hibernate enum映射详解

    hibernate enum映射详解 在这里介绍注解的形式,如果想要了解XML配置的方式,可以自行查找相关资料. 例如以下Entity @Entity @Table(name = "t_us ...

  8. [CLPR]BP神经网络的C++实现

    文章翻译自: http://www.codeproject.com/Articles/16650/Neural-Network-for-Recognition-of-Handwritten-Digi ...

  9. oracle12c之 表空间维护总结

    1.1.创建永久表空间 In the CDB:SQL> CONNECT system@cdb1SQL> CREATE TABLESPACE cdb_users DATAFILE'/home ...

  10. 【路由达人】简单两步搞定小米路由新增功能-DDNS(解析域名地址转向在线工具)

    DDNS(Dynamic Domain Name Server)是动态域名服务的缩写! 简单来说目前ISP大多为我们提供动态IP(如ADSL拨号上网),而很多设备或服务需要通过远程访问时需要一个固定的 ...