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

6 8
1 3
2 3
4 1
5 6
2 6
5 1
6 4
5 3

Sample Output

36

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

  1. bzoj 2229 [Zjoi2011]最小割(分治+最小割)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2229 [题意] 回答若干个关于割不超过x的点对数目的询问. [思路] [最小割最多有n ...

  2. bzoj4519: [Cqoi2016]不同的最小割(分治最小割)

    4519: [Cqoi2016]不同的最小割 题目:传送门 题解: 同BZOJ 2229 基本一样的题目啊,就最后用set记录一下就ok 代码: #include<cstdio> #inc ...

  3. 【BZOJ】4311: 向量(线段树分治板子题)

    题解 我们可以根据点积的定义,垂直于原点到给定点构成的直线作一条直线,从正无穷往下平移,第一个碰到的点就是答案 像什么,上凸壳哇 可是--动态维护上凸壳? 我们可以离线,计算每个点能造成贡献的一个询问 ...

  4. [模板]最小割树(Gomory-Hu Tree)(luogu4897)

    给定一个\(n\)个点\(m\)条边的无向连通图,多次询问两点之间的最小割 两点间的最小割是这样定义的:原图的每条边有一个割断它的代价,你需要用最小的代价使得这两个点不连通 Input 第一行两个数\ ...

  5. (2016北京集训十三)【xsy1532】网络战争 - 最小割树+树上倍增+KD树

    题解: 好题!! 这题似乎能上我代码长度记录的前五? 调试时间长度应该也能上前五QAQ 首先题目要求的明显就是最小割,当然在整个森林上求Q次最小割肯定是会GG的,所以我们需要一个能快速求最小割的算法— ...

  6. 【洛谷P2504】聪明的猴子 最小瓶颈树

    题目大意:给定一张 N 个顶点的完全图,边有边权,求该完全图的一棵最小瓶颈树. 最小瓶颈树:一棵最大边权值在同一张图的所有生成树中最小,即:最大边权值最小的生成树,其值为该树的最大边权的权值. 引理1 ...

  7. BZOJ 4435 [Cerc2015]Juice Junctions 分治最小割+hash

    分治最小割的题目,要求n2. 之前用的n3的方法自然不能用了. 于是用hash,设hash[i][j]表示在最小割为i的时候,j是否与S联通. 看懂这个需要理解一下最小割树的构造. 这种题建议用EK写 ...

  8. bzoj4435: [Cerc2015]Juice Junctions(最小割树+hash)

    传送门 首先最大流等于最小割,那么可以转化为最小割树来做(不知道什么是最小割树的可以看看这题->这里) 具体的做法似乎是$hash[i][j]$表示最小割为$i$时点$j$是否与$S$连通 然后 ...

  9. 【BZOJ-2229】最小割 最小割树(最大流+分治)

    2229: [Zjoi2011]最小割 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1565  Solved: 560[Submit][Status ...

随机推荐

  1. IntelliJ IDEA 快捷键备忘

    打开关闭项目结构树 Alt + 1 查看方法定义 Ctrl + B 查看方法实现 Ctrl + Alt + B 查看类结构 Ctrl + F12 弹出 或 Alt + 7 右侧栏 查看类继承结构 Ct ...

  2. ESXi 5.5 解决 cannot edit the settings of virtual machines of version 10

    ESXi 5.5 是VMWare提供的免费虚拟服务器软件, 因为其优秀的性能, 对CPU, 内存和虚拟机数量都解除了限制, 成为很多个人或者小型公司的首选虚拟化工具. 在日常管理时常碰到的一个问题是, ...

  3. mysql新建用户的方法

    新增 insert into mysql.user(Host,User,Password,ssl_cipher,x509_issuer,x509_subject) values("local ...

  4. Ruby中 使用Builder Xml Markup 操作XML

    =begin Ruby中 使用Xml Markup 轻松的对XML文档操作, 项目地址:http://builder.rubyforge.org/ 使用之前我们需要安装Builder xml mark ...

  5. JS添加DOM元素CSS权重BUG

    修改删除table的时候,比如拆分合并单元格,合并全部TR中的某个TD后在拆分还原,即使直接在td标签中设置了td的高宽属性,当td在css文件中设置为宽度auto的时候,不能显示出TD来,显示TD宽 ...

  6. 利用javascript对提交数据验证

    优点:提交前验证.在客户端进行. <html> <head> <script language="javascript"> function c ...

  7. jboss:在standalone.xml中设置系统属性(system-properties)

    就象在.net的web应用中,可以在web.config中设置appSettings一样,jboss的standalone.xml中也可以由开发人员自行添加系统属性,用法如下: </extens ...

  8. (一)GATT Profile和GAP 简介(目前所有的BLE应用都基于GATT,所以也要了解是怎么一回事)-转发

    个人大总结:(先后顺序) 1.GAP协议定义多个角色(其中就有中心设备[GATT客户端](唯一)叫主设备||和外围设备[GATT服务端端](多个)也叫从设备). 2.先经过GAP协议,再有GATT协议 ...

  9. 纯手工打造漂亮的瀑布流,五大插件一个都不少Bootstrap+jQuery+Masonry+imagesLoaded+Lightbox!

    前两天写的文章<纯手工打造漂亮的垂直时间轴,使用最简单的HTML+CSS+JQUERY完成100个版本更新记录的华丽转身!>受到很多网友的喜爱,今天特别推出姊妹篇<纯手工打造漂亮的瀑 ...

  10. c++ 指针(一)

    指针:是说指针名表示的是地址.是一个变量,存储的是值的地址,而不是值本身 *运算符被称为间接值或解除引用运算符也可以叫做取地址符 声明一个指针 int * p_data; * p_data的类型为in ...