[HZNOI #koishi] Magic
[HZNOI #514] Magic
题意
给定一个 \(n\) 个点 \(m\) 条边的有向图, 每个点有两个权值 \(a_i\) 和 \(b_i\), 可以以 \(b_i\) 的花费把第 \(i\) 个点的 \(a_i\) 变成 \(0\). 最后每个点 \(i\) 产生的花费为所有从 \(i\) 出发能通过一条有向边直接到达的点 \(j\) 的 \(a_j\) 的 \(\max\). 最小化这个过程中的总花费.
\(n\le 1000,m\le50000\)
题解
一点都不套路的最小割.
果然我是不会网络流的.
对于每个点, 如果将它的邻接点按照 \(a_j\) 降序排序的话, 不难发现必然要干掉一个前缀的所有 \(a_j\) 才能让这个点在最后统计的时候产生的花费变小. 但是多次干掉同一个点不能重复计算花费.
那么我们一点都不自然地想到最小割. 先把所有点拆成两个, 一个负责计算最终统计时的花费 (A类点), 一个负责计算被干掉的时候产生的花费 (B类点). 被干掉的时候产生的花费直接连一条流量为 \(b_i\) 的边到 \(t\) 就可以了. 最终统计时的花费先从 \(s\) 连一条 \(\infty\) 边到当前点, 然后按照 \(a_j\) 降序拉出一条链来, 链上的每个点代表一条边, 权值为这条边到达的点的 \(a_j\). 然后再从链上的每个点连一条 \(\infty\) 边到 \(j\) 对应的点. 这样的话如果 \(s\verb|-|t\) 被割断, 那么对于每一个 A 类点, 后面必然是割掉了某个 \(a_j\), 同时所有大于被割断的 \(a_j\) 的边邻接的点必然都已经被割掉了 \(b_i\).
建图Dinic就可以了.
这个拉链然后最小割的套路依然没有学会...果然我还是太菜了QAQ...
什么你问我 \(n+m\) 个点Dinic怎么跑过去的? 我怎么知道?Dinic的运行速度大概都是靠信仰吧...
恋恋世界第一!
参考代码
#include <bits/stdc++.h>
const int MAXV=1e5+10;
const int MAXE=5e6+10;
const int INF=0x7FFFFFFF;
struct Edge{
int from;
int to;
int flow;
Edge* rev;
Edge* next;
};
Edge E[MAXE];
Edge* head[MAXV];
Edge* cur[MAXV];
Edge* top=E;
int v;
int e;
int a[1010];
int b[1010];
int depth[MAXV];
std::vector<int> link[1010];
bool BFS(int,int);
int Dinic(int,int);
int DFS(int,int,int);
void Insert(int,int,int);
int main(){
freopen("magic.in","r",stdin);
freopen("magic.out","w",stdout);
scanf("%d%d",&v,&e);
for(int i=1;i<=v;i++)
scanf("%d",a+i);
for(int i=1;i<=v;i++)
scanf("%d",b+i);
for(int i=0;i<e;i++){
int a,b;
scanf("%d%d",&a,&b);
link[a].push_back(b);
}
for(int i=1;i<=v;i++)
std::sort(link[i].begin(),link[i].end(),[](int a,int b){return ::a[a]>::a[b];});
int s=0,t=1,cnt=v*2+1;
for(int i=1;i<=v;i++){
Insert(s,i+1,INF);
Insert(i+v+1,t,b[i]);
int last=i+1;
for(size_t j=0;j<link[i].size();j++){
++cnt;
Insert(cnt,v+link[i][j]+1,INF);
Insert(last,cnt,a[link[i][j]]);
last=cnt;
}
}
printf("%d\n",Dinic(s,t));
return 0;
}
int Dinic(int s,int t){
int ans=0;
while(BFS(s,t))
ans+=DFS(s,INF,t);
return ans;
}
bool BFS(int s,int t){
memset(depth,0,sizeof(depth));
std::queue<int> q;
q.push(s);
depth[s]=1;
cur[s]=head[s];
while(!q.empty()){
s=q.front();
q.pop();
for(Edge* i=head[s];i!=NULL;i=i->next){
if(i->flow>0&&depth[i->to]==0){
depth[i->to]=depth[s]+1;
cur[i->to]=head[i->to];
if(i->to==t)
return true;
q.push(i->to);
}
}
}
return false;
}
int DFS(int s,int flow,int t){
if(s==t||flow<=0)
return flow;
int rest=flow;
for(Edge*& i=cur[s];i!=NULL;i=i->next){
if(i->flow>0&&depth[i->to]==depth[s]+1){
int tmp=DFS(i->to,std::min(rest,i->flow),t);
if(tmp<=0)
depth[i->to]=0;
rest-=tmp;
i->flow-=tmp;
i->rev->flow+=tmp;
if(rest<=0)
break;
}
}
return flow-rest;
}
inline void Insert(int from,int to,int flow){
top->from=from;
top->to=to;
top->flow=flow;
top->rev=top+1;
top->next=head[from];
head[from]=top++;
top->from=to;
top->to=from;
top->flow=0;
top->rev=top-1;
top->next=head[to];
head[to]=top++;
}

[HZNOI #koishi] Magic的更多相关文章
- Codeforces CF#628 Education 8 D. Magic Numbers
D. Magic Numbers time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- [8.3] Magic Index
A magic index in an array A[0...n-1] is defined to be an index such that A[i] = i. Given a sorted ar ...
- Python魔术方法-Magic Method
介绍 在Python中,所有以"__"双下划线包起来的方法,都统称为"Magic Method",例如类的初始化方法 __init__ ,Python中所有的魔 ...
- 【Codeforces717F】Heroes of Making Magic III 线段树 + 找规律
F. Heroes of Making Magic III time limit per test:3 seconds memory limit per test:256 megabytes inpu ...
- 2016中国大学生程序设计竞赛 - 网络选拔赛 C. Magic boy Bi Luo with his excited tree
Magic boy Bi Luo with his excited tree Problem Description Bi Luo is a magic boy, he also has a migi ...
- 一个快速double转int的方法(利用magic number)
代码: int i = *reinterpret_cast<int*>(&(d += 6755399441055744.0)); 知识点: 1.reinterpret_cast&l ...
- MAGIC XPA最新版本Magic xpa 2.4c Release Notes
New Features, Feature Enhancements and Behavior ChangesSubforms – Behavior Change for Unsupported Ta ...
- Magic xpa 2.5发布 Magic xpa 2.5 Release Notes
Magic xpa 2.5發佈 Magic xpa 2.5 Release Notes Magic xpa 2.5 Release NotesNew Features, Feature Enhance ...
- How Spring Boot Autoconfiguration Magic Works--转
原文地址:https://dzone.com/articles/how-springboot-autoconfiguration-magic-works In my previous post &qu ...
随机推荐
- notepad++ jstool 插件安装
notepad++ 格式化显示 网上下载 jstool 插件 放入Notepad++\安装目录的plugins位置下,重启即可使用 插件-->JSTool
- angular $q promise详解
前言 通过本文,你大概能清楚angular promise是个啥,$q又是个啥,以及怎么用它.这里咱们先灌输下promise的思想. 下面写的全是废话,一些看着高逼格其实没什么大作用的概念,想知道$q ...
- Spring事务传播属性介绍(三).Nested
Required.Required_New传播属性分析传送门:https://www.cnblogs.com/lvbinbin2yujie/p/10259897.html Mandatory.Neve ...
- dom操作------获取元素的若干方法
// 1,getElementById:返回元素节点document.getElementById(); // 2,getElementsByClassName:返回HTMLCollection对象( ...
- 记一次webapi传参数的问题
.net小白一枚,经过了几个小时的研究,由于错误的写法导致后台始终接受不到前台传递过来的参数.首先看看控制器的参数 public Core.MVC.ServiceResult<DTO.Out.M ...
- Vue: ES6常用语法
ES6 模板字符串: ~ ${变量名}~ <div id="app"></div> <script> /* 找到对应id */ let ite ...
- Code Signal_练习题_chessBoardCellColor
Given two cells on the standard chess board, determine whether they have the same color or not. Exam ...
- SVG生成字体图标详解
- git基础使用——TortoiseGit
一.初识git Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制 ...
- C# 程序员最常犯的 10 个错误http://www.oschina.net/translate/top-10-mistakes-that-c-sharp-programmers-make
来源:http://www.oschina.net/translate/top-10-mistakes-that-c-sharp-programmers-make 关于C# C#是达成微软公共语言运行 ...