Luogu2469 SDOI2010 星际竞速 费用流
发现它的本质是求一个费用最小的路径覆盖
最小路径覆盖是网络流23题中的一个比较典型的模型
所以考虑相似的建边
因为每一个点要恰好经过一次,是一个有上下界的网络流,故拆点,星球\(i\)拆成\(A_i,B_i\)两个点,\(S->B_i , A_i -> T\),原图中的边\((i,j)\)变为\(B_i -> A_j\),费用不变。
接下来我们需要考虑费用的设置
首先\(S->B_i\)的边的费用显然是通过空间跳跃到达这个点需要的时间\(a_i\)。
但有一个问题:在上面以最小路径覆盖问题为模板建立出的模型中,点\(B_i\)的出度流对应的实际上只是一条路径上的一条边\((i,j)\)而并非一整条路径。这意味着一条路径上除了终点以外所有点的\(a_i\)在费用流中都被加了进来。
考虑怎么减掉这个额外出现的空间跳跃费用。不难想到将\(A_i -> T\)边的费用设置为\(-a_i\)。这样非起点非终点的所有点\(a_i\)的贡献就会变为\(0\)。但是在这种情况下终点\(a_i\)的贡献却又是\(-a_i\)。
发现问题在于\(S->B_i\)边没有流。那么加上\(B_i -> T\)、流量1费用0的边,这样\(S->B_i\)就会有\(1\)的流,终点的空间跳跃时间就会变为\(0\),就能保证路径上所有点空间跳跃时间是正确的了。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<vector>
#include<cmath>
#define INF 0x3f3f3f3f
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = (a << 3) + (a << 1) + (c ^ '0');
c = getchar();
}
return f ? -a : a;
}
const int MAXN = 2e4 + 3 , MAXM = 1e5 + 3;
struct Edge{
int end , upEd , f , c;
}Ed[MAXM];
int head[MAXN] , cur[MAXN] , dep[MAXN] , dis[MAXN] , pre[MAXN] , flo[MAXN];
int N , M , S , T , cntEd = 1;
bool vis[MAXN];
queue < int > q;
inline void addEd(int a , int b , int c , int d = 0){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
Ed[cntEd].f = c;
Ed[cntEd].c = d;
head[a] = cntEd;
}
inline bool bfs(){
while(!q.empty())
q.pop();
q.push(S);
memset(dep , 0 , sizeof(dep));
dep[S] = 1;
while(!q.empty()){
int t = q.front();
q.pop();
for(int i = head[t] ; i ; i = Ed[i].upEd)
if(Ed[i].f && !dep[Ed[i].end]){
dep[Ed[i].end] = dep[t] + 1;
if(Ed[i].end == T){
memcpy(cur , head , sizeof(head));
return 1;
}
q.push(Ed[i].end);
}
}
return 0;
}
inline int dfs(int x , int mF){
if(x == T)
return mF;
int sum = 0;
for(int &i = cur[x] ; i ; i = Ed[i].upEd)
if(Ed[i].f && dep[Ed[i].end] == dep[x] + 1){
int t = dfs(Ed[i].end , min(mF - sum , Ed[i].f));
if(t){
Ed[i].f -= t;
Ed[i ^ 1].f += t;
sum += t;
if(sum == mF)
break;
}
}
return sum;
}
int Dinic(){
int ans = 0;
while(bfs())
ans += dfs(S , INF);
return ans;
}
inline bool SPFA(){
memset(dis , 0x3f , sizeof(dis));
dis[S] = 0;
while(!q.empty())
q.pop();
q.push(S);
flo[S] = INF;
while(!q.empty()){
int t = q.front();
q.pop();
vis[t] = 0;
for(int i = head[t] ; i ; i = Ed[i].upEd)
if(Ed[i].f && dis[Ed[i].end] > dis[t] + Ed[i].c){
dis[Ed[i].end] = dis[t] + Ed[i].c;
flo[Ed[i].end] = min(Ed[i].f , flo[t]);
pre[Ed[i].end] = i;
if(!vis[Ed[i].end]){
vis[Ed[i].end] = 1;
q.push(Ed[i].end);
}
}
}
return dis[T] != dis[T + 1];
}
int EK(){
int ans = 0;
while(SPFA()){
int cur = T , sum = 0;
while(cur != S){
sum += Ed[pre[cur]].c;
Ed[pre[cur]].f -= flo[T];
Ed[pre[cur] ^ 1].f += flo[T];
cur = Ed[pre[cur] ^ 1].end;
}
ans += sum * flo[T];
}
return ans;
}
bool in[MAXN];
int nxt[MAXN];
int main(){
#ifndef ONLINE_JUDGE
freopen("in" , "r" , stdin);
//freopen("out" , "w" , stdout);
#endif
N = read();
M = read();
T = 2 * N + 2;
for(int i = 1 ; i <= N ; ++i){
int a = read();
addEd(S , i + N , 1 , a);
addEd(i + N , S , 0 , -a);
addEd(i , T , 1 , -a);
addEd(T , i , 0 , a);
addEd(i + N , T - 1 , 1);
addEd(T - 1 , i + N , 0);
}
addEd(T - 1 , T , INF);
addEd(T , T - 1 , 0);
for(int i = 1 ; i <= M ; ++i){
int a = read() , b = read() , c = read();
if(a > b)
swap(a , b);
addEd(a + N , b , 1 , c);
addEd(b , a + N , 0 , -c);
}
cout << EK();
return 0;
}
Luogu2469 SDOI2010 星际竞速 费用流的更多相关文章
- BZOJ 1927: [Sdoi2010]星际竞速 费用流
1927: [Sdoi2010]星际竞速 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- BZOJ 1927: [Sdoi2010]星际竞速(费用流)
传送门 解题思路 仿照最小路径覆盖问题,用费用流解决此题.最小路径覆盖问题是拆点连边后用\(n-\)最大匹配,这里的话也是将每个点拆点,源点向入点连流量为\(1\),费用为\(0\)的边,向出点连流量 ...
- [SDOI2010]星际竞速——费用流
类似于最短路的网络流,而且还要保证每个点经过一次,拆点就比较方便了. 连边怎么连?要保证最大流是n(每个点经过一次)还要能从直接跳转 将每个点拆点.源点向每个点的入点连一条容量为1费用为0的边.源点向 ...
- BZOJ 1927 星际竞速(费用流)
考虑费用流,题目要求走n个点都走完且恰好一次,显然流量的限制为n. 建立源点s和汇点t,并把每个星球拆成两个点i和i',分别表示已到达该点和经过该点. 对于能力爆发,建边(s,i',1,w). 对应高 ...
- bzoj 1927 [Sdoi2010]星际竞速(最小费用最大流)
1927: [Sdoi2010]星际竞速 Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 1576 Solved: 954[Submit][Statu ...
- BZOJ 1927: [Sdoi2010]星际竞速(最小费用最大流)
拆点,费用流... ----------------------------------------------------------------------------- #include< ...
- BZOJ 1927: [Sdoi2010]星际竞速 [上下界费用流]
1927: [Sdoi2010]星际竞速 题意:一个带权DAG,每个点恰好经过一次,每个点有曲速移动到他的代价,求最小花费 不动脑子直接上上下界费用流过了... s到点连边边权为曲速的代价,一个曲速移 ...
- BZOJ1927 [Sdoi2010]星际竞速 【费用流】
1927: [Sdoi2010]星际竞速 Time Limit: 20 Sec Memory Limit: 259 MB Submit: 2582 Solved: 1601 [Submit][St ...
- P2469 [SDOI2010]星际竞速(费用流)
P2469 [SDOI2010]星际竞速 最小路径覆盖问题 每个星球必须恰好去一次,而每次高速航行都是从一个星球到另一个星球. 那么高速航行的起点可以保证被去过 高速航行和空间跳跃可以是互相独立的 将 ...
随机推荐
- :hover在ios无效问题
:hover 设置的样式在ios显示不出来,需要在按钮元素或body/html上绑定一个touchstart事件才能激活:active状态. 解决方案: 方案1 js绑定: document.body ...
- 卷积神经网络CNNs的理解与体会
https://blog.csdn.net/shijing_0214/article/details/53143393 孔子说过,温故而知新,时隔俩月再重看CNNs,当时不太了解的地方,又有了新的理解 ...
- 机器学习算法(SVM)公开课4月25日开讲
从深蓝到AlphaGo,聪明的人工智能一再“羞辱”人类大脑: 指纹识别.以图搜图.语音助手.无人驾驶···生活里它无孔不入 离不开智能手机的我们,是否已开始被人工智能的“奴役”? 或许,你不需要会运用 ...
- mysql 优化配置参数(my.cnf)
max_connections:允许客户端并发连接的最大数量,默认值是151,一般将该参数设置为500-2000max_connect_errors:如果客户端尝试连接的错误数量超过这个参数设置的值, ...
- loadrunner 脚本开发-基本知识
脚本开发-基本知识 1)编码工具设置 自动补全输入Tools->General Options->Environment->Auto complete word 显示功能语法Tool ...
- 安卓开发_浅谈Notification(通知栏)
Notification通知栏是显示在手机状态的消息,代表一种全局效果的通知 快速创建一个Notification的步骤简单可以分为以下四步: 第一步:通过getSystemService()方法得到 ...
- 安卓开发_深入理解Content Provider
一.Content Provider概述 Content Provider用于保存和获取数据,并使其对所有应用程序可见,这是不同应用程序之间共享数据的唯一方式,因为在Android中没有提供所有应用可 ...
- [20180625]oradebug peek 2.txt
[20180625]oradebug peek 2.txt --//上个星期演示了oradebug peek查看内存数据块的情况,oradebug peek {address} length 1,最后 ...
- 04-openldap客户端安装
阅读视图 基础环境准备 关闭sssd及安装nslcd客户端 配置nslcd客户端 启动nslcd进程 客户端验证 ssh登录自动创建家目录 1. 基础环境准备 本文承接openldap服务端安装配置, ...
- 关于excel中的查找
弹出查找界面后,点击“选项”按钮 在范围下拉框中选择: 1.工作表:表示在当前表sheet中进行查找 2.工作簿:表示在此excel整个文件中进行查找