【BZOJ-4435】Juice Junctions 最小割树(分治+最小割)+Hash
4435: [Cerc2015]Juice Junctions
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 20 Solved: 11
[Submit][Status][Discuss]
Description
你被雇佣升级一个旧果汁加工厂的橙汁运输系统。系统有管道和节点构成。每条管道都是双向的,且每条管道的流量都是1升每秒。管道可能连接节点,每个节点最多可以连接3条管道。节点的流量是无限的。节点用整数1到n来表示。在升级系统之前,你需要对现有系统进行分析。对于两个不同节点s和t,s-t的流量被定义为:当s为源点,t为汇点,从s能流向t的最大流量。以下面的第一组样例数据为例,1-6的流量为3,1-2的流量为2。计算每一对满足a<b的节点a-b的流量的和。
Input
第一行包括2个整数n和m(2<=n<=3000,0<=m<=4500)——节点数和管道数。
接下来m行,每行包括两个相异整数a,b(1<=a,b<=n),表示一条管道连接节点a,b。
每个节点最多连接3条管道,每对节点最多被一条管道连接。
Output
输出一个整数——每对满足a<b的节点a-b的流量之和。
Sample Input
1 3
2 3
4 1
5 6
2 6
5 1
6 4
5 3
Sample Output
HINT
Source
Solution
最小割树+Hash
根据最大流-最小割定理,把求最大流转化为求最小割,那么最小割树搞搞
因为每个点的度有限制,所以最小割不能超过3
把最小割hash出来,然后求和即可,大体的hash就是$hash[i][j]$表示最小割为$i$的时候,$j$点在分治过程中是否于$S$连通
PS:据说这题卡Dinic和ISAP的常数,只能用EK,但是好像Dinic能跑过?
UPD:事后和CA爷Claris讨论起来,EK是根据流量的复杂度,常数小,实用于这题;但我说Dinic也能过啊,慢了1倍是真的...然后得知原题时限7s....丧心病狂
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
int n,m;
#define maxm 10010
#define maxn 3010
struct Edgenode{int next,cap,to;}edge[maxm];
int head[maxn],cnt=;
void add(int u,int v,int w)
{
cnt++;
edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].cap=w;
}
void insert(int u,int v,int w)
{
add(u,v,w); add(v,u,w);
}
int dis[maxn],que[maxn<<],cur[maxn],S,T;
bool bfs()
{
for (int i=; i<=n; i++) dis[i]=-;
que[]=S; dis[S]=; int he=,ta=;
while (he<ta)
{
int now=que[he++];
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==-)
dis[edge[i].to]=dis[now]+,que[ta++]=edge[i].to;
}
return dis[T]!=-;
}
int dfs(int loc,int low)
{
if (loc==T) return low;
int w,used=;
for (int i=cur[loc]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==dis[loc]+)
{
w=dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap-=w; edge[i^].cap+=w;
used+=w; if (edge[i].cap) cur[loc]=i;
if (used==low) return low;
}
if (!used) dis[loc]=-;
return used;
}
#define inf 0x7fffffff
int dinic()
{
int tmp=;
while (bfs())
{
for (int i=; i<=n; i++) cur[i]=head[i];
tmp+=dfs(S,inf);
}
return tmp;
}
bool visit[maxn];
void DFS(int x)
{
visit[x]=;
for (int i=head[x]; i; i=edge[i].next)
if (!visit[edge[i].to] && edge[i].cap)
DFS(edge[i].to);
}
int id[maxn],tmp[maxn];
unsigned BASE=,hash[][maxn];
void work(int L,int R)
{
if (L==R) return;
for (int i=; i<=cnt; i+=)
edge[i].cap=edge[i^].cap=(edge[i].cap+edge[i^].cap)>>;
S=id[L],T=id[R];
int maxflow=dinic();
memset(visit,,sizeof(visit)); DFS(S);
BASE*=;
for (int i=; i<=n; i++) if (~dis[i]) hash[maxflow][i]+=BASE;
int l=L,r=R;
for (int i=L; i<=R; i++)
if (visit[id[i]]) tmp[l++]=id[i];
else tmp[r--]=id[i];
for (int i=L; i<=R; i++) id[i]=tmp[i];
work(L,l-); work(r+,R);
}
int ans=;
int main()
{
n=read(),m=read();
for (int u,v,i=; i<=m; i++)
u=read(),v=read(),insert(u,v,);
for (int i=; i<=n; i++) id[i]=i;
work(,n);
for (int i=; i<=n; i++)
for (int j=i+; j<=n; j++)
for (int k=; k<=; k++)
if (hash[k][i]!=hash[k][j]) {ans+=k;break;}
printf("%d\n",ans);
return ;
}
被卡常数的教育:(成功垫底.....)
【BZOJ-4435】Juice Junctions 最小割树(分治+最小割)+Hash的更多相关文章
- bzoj 2229 [Zjoi2011]最小割(分治+最小割)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2229 [题意] 回答若干个关于割不超过x的点对数目的询问. [思路] [最小割最多有n ...
- bzoj4519: [Cqoi2016]不同的最小割(分治最小割)
4519: [Cqoi2016]不同的最小割 题目:传送门 题解: 同BZOJ 2229 基本一样的题目啊,就最后用set记录一下就ok 代码: #include<cstdio> #inc ...
- 【BZOJ】4311: 向量(线段树分治板子题)
题解 我们可以根据点积的定义,垂直于原点到给定点构成的直线作一条直线,从正无穷往下平移,第一个碰到的点就是答案 像什么,上凸壳哇 可是--动态维护上凸壳? 我们可以离线,计算每个点能造成贡献的一个询问 ...
- [模板]最小割树(Gomory-Hu Tree)(luogu4897)
给定一个\(n\)个点\(m\)条边的无向连通图,多次询问两点之间的最小割 两点间的最小割是这样定义的:原图的每条边有一个割断它的代价,你需要用最小的代价使得这两个点不连通 Input 第一行两个数\ ...
- (2016北京集训十三)【xsy1532】网络战争 - 最小割树+树上倍增+KD树
题解: 好题!! 这题似乎能上我代码长度记录的前五? 调试时间长度应该也能上前五QAQ 首先题目要求的明显就是最小割,当然在整个森林上求Q次最小割肯定是会GG的,所以我们需要一个能快速求最小割的算法— ...
- 【洛谷P2504】聪明的猴子 最小瓶颈树
题目大意:给定一张 N 个顶点的完全图,边有边权,求该完全图的一棵最小瓶颈树. 最小瓶颈树:一棵最大边权值在同一张图的所有生成树中最小,即:最大边权值最小的生成树,其值为该树的最大边权的权值. 引理1 ...
- BZOJ 4435 [Cerc2015]Juice Junctions 分治最小割+hash
分治最小割的题目,要求n2. 之前用的n3的方法自然不能用了. 于是用hash,设hash[i][j]表示在最小割为i的时候,j是否与S联通. 看懂这个需要理解一下最小割树的构造. 这种题建议用EK写 ...
- bzoj4435: [Cerc2015]Juice Junctions(最小割树+hash)
传送门 首先最大流等于最小割,那么可以转化为最小割树来做(不知道什么是最小割树的可以看看这题->这里) 具体的做法似乎是$hash[i][j]$表示最小割为$i$时点$j$是否与$S$连通 然后 ...
- 【BZOJ-2229】最小割 最小割树(最大流+分治)
2229: [Zjoi2011]最小割 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1565 Solved: 560[Submit][Status ...
随机推荐
- Swift关于Any,AnyObject,AnyClass的区别与联系
在Swift语言中,协议定义类或结构体应该遵守的变量和方法集合,如下所示,这个一个标准的协议的声明: protocol NSObjectProtocol { func isEqual(object: ...
- Hibernate总结3
一,对象的四种状态 临时状态: 与数据库没有对应,跟Session没有关联. 一般是新new出的对象. 持久化状态: 对象在Session的管理之中,最终会有对应的数据库记录.save saveoru ...
- usb驱动开发16之设备生命线
回到struct usb_hcd,继续努力的往下看. kref,usb主机控制器的引用计数.struct usb_hcd也有自己专用的引用计数函数,看hcd.c文件. static void hcd_ ...
- node基础05:路由基础
1.基础实例 //server.js var http = require("http"); var url = require("url"); var rou ...
- 【LeetCode】95. Unique Binary Search Trees II
Unique Binary Search Trees II Given n, generate all structurally unique BST's (binary search trees) ...
- linux中vi编辑器的使用
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本 编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任 何版本,vi编辑器是完 ...
- Canvas之蛋疼的正方体绘制体验
事情的起因 之前写了篇谈谈文字图片粒子化 I,并且写了个简单的demo -> 粒子化.正当我在为写 谈谈文字图片粒子化II 准备demo时,突然想到能不能用正方体代替demo中的球体粒子.我不禁 ...
- 判断Laravel Eloquent获取数据结果集是否为空
在使用Laravel Eloquent模型时,我们可能要判断取出的结果集是否为空,但我们发现直接使用is_null或empty是无法判段它结果集是否为空的. var_dump之后我们很容易发现,即使取 ...
- HoloLens开发手记 - Vuforia开发概述 Vuforia development overview
关于Vuforia,开发AR应用的人基本都会熟悉.之前我也写过一篇关于Vuforia开发的博客:Vuforia AR SDK入门 今天这篇博客则主要是谈谈HoloLens使用Vuforia开发混合现实 ...
- Python 处理数据库返回结果
游标执行后返回的结果都只是数据,但是不带有列名标识.这里需要处理2个问题: 将返回的数据映射到每一列上 当返回的结果很大的时候,需要使用迭代器来提升性能. 解决上面的2个问题,在python里面可以采 ...