Luogu P4553 80人环游世界
题目大意
自东向西有 \(n\) 个国家。有 \(m\) 个人,他们可以选择 \(n\) 个国家中任意一个开始,任意一个结束,但路线必须自东向西,且第 \(i\) 个国家必须恰好经过 \(v_i\) 人。已知每个国家到它西方的国家的费用,求最小花费。
最小费用最大流
蒟蒻不会上下界,看了一些大佬写的费用流,想了一下,发表一下自己的理解,希望对大家有帮助。
首先因为对于每个点(国家)都有经过限制,所以将拆点为入点和出点。 \(i\rightarrow (i,i+n)\)
\(s\) 向第 \(i\) 入点连容量 \(v_i\) 费用 \(0\) 的边,因为每个国家必须要有 \(v_i\) 人来,连这条边就相当于这 \(v_i\) 个人进入了该国。
同理,出点向 \(t\) 连容量 \(v_i\)费用 \(0\) 的边,表示有 \(v_i\) 个人到达了这个国家。
对于每条航线 \((u,v)\),由 \(u\) 的入点向 \(v\) 的出点连容量 \(\infty\) 费用 \(0\) 的边,表示进入国家 \(u\) 的人可以前往国家 \(v\) 并声明到达了国家 \(v\) (即从 \(v\) 的出点到达汇点)。
最后额外再建一个点,由 \(s\) 向它连容量 \(m\) 费用 \(0\) 的边,然后让他向每个出点连容量 \(\infty\) 费用 \(0\) 的边表示这 \(m\) 个人可以随便选出发点。
然后跑最小费用最大流即可。
考虑正确性:因为跑的是最大流,所以每个出点到汇点的边一定会跑满,也就保证了每个国家限定经过次数。
又因为从那个额外点到其他出点的边费用为 \(0\) 所以这些边会被优先选择,也就意味着从源点到额外点着条边一定会跑满,也就意味着这 \(m\) 个人一定会出发(不会有人临阵脱逃)。
Code
#include<bits/stdc++.h>
//#define int long long
#define pair pair<int,int>
using namespace std;
inline void end()
{
puts("");
system("pause");
}
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
const int N=222,M=2e4+4,inf=0x3f3f3f3f,INF=1e9;
int s,t,maxf,minc;
int first[N],nex[M],to[M],w[M],c[M],num=1;
inline void add(int u,int v,int val,int cos)
{
nex[++num]=first[u];
first[u]=num;
to[num]=v;
w[num]=val;
c[num]=cos;
}
inline void Add(int u,int v,int val,int cos)
{
add(u,v,val,cos);
add(v,u,0,-cos);
}
int dis[N],vis[N],cur[N];
inline bool SPFA()
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
deque<int> q;
q.push_back(s);
vis[s]=1;dis[s]=0;
while(!q.empty())
{
int u=q.front();q.pop_front();vis[u]=0;
for(int i=first[u];i;i=nex[i])
{
int v=to[i];
if(!w[i]) continue;
if(dis[v]>dis[u]+c[i])
{
dis[v]=dis[u]+c[i];
if(!vis[v])
{
vis[v]=1;
if(q.empty()||dis[v]>dis[q.front()]) q.push_back(v);
else q.push_front(v);
}
}
}
}
if(dis[t]==inf) return 0;
return 1;
}
int dfs(int u,int in)
{
if(u==t) return in;
vis[u]=1;
int out=0;
for(int i=cur[u];i;i=nex[i])
{
int v=to[i];
if(!w[i]||vis[v]) continue;
if(dis[v]==dis[u]+c[i])
{
int res=dfs(v,min(w[i],in-out));
w[i]-=res;
w[i^1]+=res;
out+=res;
minc+=c[i]*res;
if(in==out) break;
}
}
vis[u]=0;
if(!out) vis[u]=1;
return out;
}
void Dinic()
{
while(SPFA())
{
memcpy(cur,first,sizeof(first));
while(1)
{
int detal=dfs(s,1e9);
if(!detal) break;
maxf+=detal;
}
}
}
int n,m,v[N],ex;
main()
{
n=read(),m=read();ex=2*n+1;s=0,t=ex+1;
//ex为额外点
Add(s,ex,m,0);
for(int i=1;i<=n;++i)
{
v[i]=read();
Add(i+n,t,v[i],0);
Add(ex,i+n,INF,0);
}
for(int i=1;i<=n;++i)
{
Add(s,i,v[i],0);
for(int j=i+1;j<=n;++j)
{
int val=read();
if(val==-1) continue;
Add(i,j+n,INF,val);
}
}
Dinic();//最小费用最大流
printf("%d",minc);
//end();
return 0;
}
Luogu P4553 80人环游世界的更多相关文章
- P4553 80人环游世界
题目地址:P4553 80人环游世界 上下界网络流 无源汇上下界可行流 给定 \(n\) 个点, \(m\) 条边的网络,求一个可行解,使得边 \((u,v)\) 的流量介于 \([B(u,v),C( ...
- P4553 80人环游世界(上下界费用流)
P4553 80人环游世界 emm......先从上下界网络流(转)开始 再到现在的上下界费用流 因为有上下界,我们需要记下每个点的流量差$ex[i]$,用于调整 $ins(x,y,l,r,v)=li ...
- 洛谷P4553 80人环游世界
题目描述 https://www.luogu.org/problemnew/show/P4553 题解 思路比较显然,把图建出来,一个国家拆成两个点,中间设置上下界,然后跑费用流. 我把源那边的流量也 ...
- 【BZOJ-2055】80人环游世界 上下界费用流 (无源无汇最小费用最大流)
2055: 80人环游世界 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 321 Solved: 201[Submit][Status][Discus ...
- BZOJ2055: 80人环游世界
题解: 总算A掉了,各种蛋疼... int main() { freopen("input.txt","r",stdin); freopen("out ...
- BZOJ 2055: 80人环游世界 [上下界费用流]
2055: 80人环游世界 题意:n个点带权图,选出m条路径,每个点经过val[i]次,求最小花费 建图比较简单 s拆点限制流量m 一个点拆成两个,限制流量val[i],需要用上下界 图中有边的连边, ...
- [BZOJ2055]80人环游世界 有上下界最小费用最大流
2055: 80人环游世界 Time Limit: 10 Sec Memory Limit: 64 MB Description 想必大家都看过成龙大哥的<80天环游世界>,里面 ...
- bzoj 2055: 80人环游世界 -- 上下界网络流
2055: 80人环游世界 Time Limit: 10 Sec Memory Limit: 64 MB Description 想必大家都看过成龙大哥的<80天环游世界>,里面 ...
- 【BZOJ】2055 80人环游世界
[算法]有源汇上下界最小费用可行流 [题解]上下界 因为上下界相同,所以无所谓最小流了,可行流(初始流+附加流)就是答案了. 记得源点向新建节点连一条容量为m(人)的边. bzoj 2055 80人环 ...
随机推荐
- opencv——自适应阈值Canny边缘检测
前言 Canny边缘检测速度很快,OpenCV中经常会用到Canny边缘检测,以前的Demo中使用Canny边缘检测都是自己手动修改高低阈值参数,最近正好要研究点小东西时,就想能不能做个自适应的阈值, ...
- 解决Caused by: org.apache.ibatis.exceptions.PersistenceException:
在mybatis-config核心配置文件中注册了xml以后出现了新的异常错误 Caused by: java.io.IOException: Could not find resource cn.d ...
- 十一、.net core(.NET 6)搭建ElasticSearch(ES)系列之ElasticSearch、head-master、Kibana环境搭建
搭建ElasticSearch+Kibana环境 前提条件:已经配置好JDK环境以及Nodejs环境.如果还未配置,请查看我的上一篇博客内容,有详细配置教程. 先下载ElasticSearch(以下文 ...
- volatile 关键字笔记
你应该知道的 volatile 关键字 当一个变量被 volatile 修饰时,任何线程对它的写操作都会立即刷新到主内存中,并且会强制让缓存了该变量的线程中的数据清空,必须从主内存重新读取最新数据. ...
- Python3 url解码与参数解析
Python3 url解码与参数解析 有些子节点名字直接就是编码后的url,就像下面这行一样: url='dubbo%3A%2F%2F10.4.5.3%3A20880%2Fcom.welab.auth ...
- Go基础结构与类型01---常量变量表达式
// 包名(main包下的main函数是程序的入口) package main // 导入sdk(software developing kit)中的fmt包 import "fmt&quo ...
- Apollo 自动驾驶开发套件(D-KIT)
Apollo 自动驾驶开发套件(D-KIT)
- Jittor 的Op, Var算子
Jittor 的Op, Var算子 要使用jittor训练模型,需要了解两个主要概念: Var:Jittor的基本数据类型 Operations:Jittor的算子与numpy类似 首先,开始使用Va ...
- AIoT开放平台及应用
AIoT开放平台及应用 阿里AIoT开放平台,是阿里云IoT面向开发者的能力接入渠道,开发者可以在这里完成能力的申请.开通.部署.配置和集成开发等一些列工作.这些能力并不的独立交付,而是通过关联到行业 ...
- 使用NVIDIA GRID vPC支持视频会议和算力工具
随着2020年的发展,远程工作解决方案已成为许多人的新常态.企业正在寻找行之有效的解决方案,如虚拟桌面基础设施(VDI),以使他们的团队能够在任何地方安全地工作.然而,最新的算力和视频会议应用程序需要 ...