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人环 ...
随机推荐
- VMware vRealize Network Insight 6.2 发布 - 网络和安全可视化分析
发现.优化应用安全性和网络连接解决方案并对其进行故障排除 VMware vRealize Network Insight 可帮助您跨混合和多云环境构建经过优化且高度可用的安全网络基础架构.它提供了网络 ...
- 同一个Controller里的同一个Service实例,在当前的Controller里的不同方法中状态不一致
直接上代码如下: @Controller@RequestMapping("/views/information")public class PubContentController ...
- MySQL 5.7.33 超级详细下载安装配置测试教程(可以安装成功版)
目录 1.引言及注意事项 (1) 引言: (2) 注意: 2.MySQL下载 3.配置环境变量 4.配置my.ini文件(重点) 5.安装MySQL(重点) 6.设置密码 7.测试MySQL是否安装成 ...
- Kettle通过Http post请求webservice接口以及结果解析处理
kettle中有两种方式请求webservice服务,一个是Web服务查询,但是这个有缺陷,无法处理复杂的需求,遇到这种情况就需要用Http post来处理了. 网上也有很多关于Http post请求 ...
- 数据结构与算法Python版 熟悉哈希表,了解Python字典底层实现
Hash Table 散列表(hash table)也被称为哈希表,它是一种根据键(key)来存储值(value)的特殊线性结构. 常用于迅速的无序单点查找,其查找速度可达到常数级别的O(1). 散列 ...
- Docker与k8s的恩怨情仇(一)—成为PaaS前浪的Cloud Foundry
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 大家在工作中或许或多或少都接触过Docker,那你知道Docker以及容器化背后的原理到底是什么吗? 容器化 ...
- 【NX二次开发】根据视图名称旋转视图,在布局中替换视图uc6464
uc6464("布局名","旧视图名","新视图名");输入布局名.旧视图名.新视图名.如果布局名为空则更新当前布局.如果旧视图名为空,则工 ...
- Java on Visual Studio Code的更新 – 2021年5月
杨尧今 from Microsoft VS Code Java Team 欢迎来到 5月的 VS Code for Java 更新.这次,我们将与您分享Java格式化设置编辑器和其他很酷的功能.开始吧 ...
- Reactive Spring实战 -- 响应式Kafka交互
本文分享如何使用KRaft部署Kafka集群,以及Spring中如何实现Kafka响应式交互. KRaft 我们知道,Kafka使用Zookeeper负责为kafka存储broker,Consumer ...
- 在vue中下拉框切换事件中改新建表单中的一个值,页面不显示
事件中改新建表单中的一个值,页面不显示,当另一个对象值发生改变时,这个页面上的值才会显示 由于新建表单是弹窗,在弹出时会重新给每个字段重新赋值,在赋值时没给这个字段赋值(常见新加功能时,加了一个字段, ...