[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的更多相关文章

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

  2. [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 ...

  3. Python魔术方法-Magic Method

    介绍 在Python中,所有以"__"双下划线包起来的方法,都统称为"Magic Method",例如类的初始化方法 __init__ ,Python中所有的魔 ...

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

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

  6. 一个快速double转int的方法(利用magic number)

    代码: int i = *reinterpret_cast<int*>(&(d += 6755399441055744.0)); 知识点: 1.reinterpret_cast&l ...

  7. MAGIC XPA最新版本Magic xpa 2.4c Release Notes

    New Features, Feature Enhancements and Behavior ChangesSubforms – Behavior Change for Unsupported Ta ...

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

  9. How Spring Boot Autoconfiguration Magic Works--转

    原文地址:https://dzone.com/articles/how-springboot-autoconfiguration-magic-works In my previous post &qu ...

随机推荐

  1. C/C++编程GUI库比较

    转自:http://blog.csdn.net/lostown/article/details/658654 最强的GUI库当属Qt,毕竟是商业化的东西,功能最完整,什么都好,包括类似java代码风格 ...

  2. asp.net mvc 学习笔记 - 单一实例设计模式

    学习之前,先喊一下口号:每天进步一点,生活更好一点 首先声明一点,我也是新新新手一枚,崭新的新哦.如果文章有不合理的地方,也请各位博友多多指点,不要乱喷哦 我的文采很低调,低调到语文老师对我的期望是你 ...

  3. .16-浅析webpack源码之编译后流程梳理

    这节把编译打包后的流程梳理一下,然后集中处理compile. 之前忽略了一个点,如下: new NodeEnvironmentPlugin().apply(compiler); // 引入插件加载 i ...

  4. .39-浅析webpack源码之parser.parse

    因为换了个工作,所以博客停了一段时间. 这是上个月留下来的坑,webpack的源码已经不太想看了,又臭又长,恶心的要死,想去看node的源码……总之先补完这个 上一节完成了babel-loader对J ...

  5. #if _MSC_VER &gt; 1000 #pragma once #endif 含义

    前提:MFC应用程序中,MainFrm 类头文件 MainFrm.h 中#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000解释 ...

  6. Android-Menu菜单使用一

    创建菜单 在AndroidSDK中,无需从头创建菜单对象.因为一个活动只与一个菜单关联,所以Android会为该活动创建此菜单,然后将它传给Activity类的onCreateOptionsMenu回 ...

  7. Java生成代码(字节码)

    一.方式 代码生成器 & IDE 编译时代码生成: Pluggable Annotation Processing API 运行时代码生成: Compiler API 运行时生成字节码: cg ...

  8. POJ3264(KB7-G RMQ)

    Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K   otal Submissions: 52651 Case Time Limit: 2 ...

  9. php中的或运算

    1.今天碰到一个php或运算的面试题,很有趣,和大家分享一下.开始不明白什么原因. <?php $a = 0; $b = 0; if($a=3)>0 || ($b=3)>0) { $ ...

  10. Code Signal_练习题_digitDegree

    Let's define digit degree of some positive integer as the number of times we need to replace this nu ...