BZOJ 4435 [双连通分量][Hash]

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

Description

你被雇佣升级一个旧果汁加工厂的橙汁运输系统。系统有管道和节点构成。每条管道都是双向的,且每条管道的流量都是1升每秒。管道可能连接节点,每个节点最多可以连接3条管道。节点的流量是无限的。节点用整数1n来表示。在升级系统之前,你需要对现有系统进行分析。对于两个不同节点stst的流量被定义为:当s为源点,t为汇点,从s能流向t的最大流量。以下面的第一组样例数据为例,16的流量为312的流量为2。计算每一对满足a<b的节点ab的流量的和。

Solution

根据最大流最小割定理,我们要求的其实就是最小割。题中所说每个节点只会连出至多三条边,显然最小割至多为3。分类讨论一下:
若最小割为0:说明两点之间不连通。
若最小割为1:说明两点处于不同的双连通分量中。
若最小割为23:考虑从图中删去一条边,若删去任何一条边之后两个点仍在同一双连通分量中,则说明最小割为3否则为2
如何判断删去任意一条边之后的双连通分量编号是否相同,只需要对每个点Hash一下。(注意要是有序的Hash)。
时间复杂度O(n2)

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

inline char get(void) {
  static char buf[100000], *S = buf, *T = buf;
  if (S == T) {
    T = (S = buf) + fread(buf, 1, 100000, stdin);
    if (S == T) return EOF;
  }
  return *S++;
}
inline void read(int &x) {
  static char c; x = 0;
  for (c = get(); c < '0' || c > '9'; c = get());
  for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}

const int N = 3030;
const int M = 4545;
const int P = 2333333;
typedef long long ll;

struct edge {
  int to, next;
  edge (int t = 0, int n = 0):to(t), next(n) {}
};
edge G[M << 1];
int pre[N], low[N], bcc[N], sta[N];
int has[N], mark[M << 1], id[N];
int head[N];
int ans[N][N];
int n, m, x, y, Gcnt, clc, top, Bcnt, cnt, Ans;

inline int Min(int a, int b) {
  return a < b ? a : b;
}
inline void AddEdge(int from, int to) {
  G[++Gcnt] = edge(to, head[from]); head[from] = Gcnt;
  G[++Gcnt] = edge(from, head[to]); head[to] = Gcnt;
}
void dfs(int u, int fa) {
  low[u] = pre[u] = ++clc;
  int to; id[u] = cnt;
  sta[++top] = u;
  for (int i = head[u]; i; i = G[i].next)
    if (!mark[i]) {
      to = G[i].to;
      if (pre[to]) {
        if (to != fa) low[u] = Min(low[u], low[to]);
      } else if (to != fa) {
        dfs(to, u); low[u] = Min(low[u], low[to]);
      }
    }
  if (low[u] == pre[u]) {
    Bcnt++;
    while (sta[top] != u) {
      bcc[sta[top]] = Bcnt;
      top--;
    }
    bcc[sta[top--]] = Bcnt;
  }
}
void SetBcc(int flag = 0) {
  Bcnt = cnt = clc = top = 0;
  memset(pre, 0, sizeof pre);
  memset(id, 0, sizeof id);
  for (int i = 1; i <= n; i++)
    if (!pre[i]) {
      cnt++; dfs(i, 0);
    }
  if (flag) return (void)("%%%%gjghfd%%%%");
  for (int i = 1; i <= n; i++)
    has[i] = ((ll)has[i] * M % P + bcc[i]) % P;
}

int main(void) {
  freopen("1.in", "r", stdin);
  freopen("1.out", "w", stdout);
  read(n); read(m);
  for (int i = 1; i <= m; i++) {
    read(x); read(y);
    AddEdge(x, y);
  }
  SetBcc(1);
  for (int i = 1; i <= n; i++)
    for (int j = i + 1; j <= n; j++) {
      if (bcc[i] != bcc[j]) ans[i][j] = 1;
      if (id[i] != id[j]) ans[i][j] = -1;
    }
  for (int i = 1; i <= Gcnt; i += 2) {
    mark[i] = mark[i + 1] = 1;
    SetBcc();
    mark[i] = mark[i + 1] = 0;
  }
  for (int i = 1; i <= n; i++)
    for (int j = i + 1; j <= n; j++) {
      if (ans[i][j] != 0) continue;
      if (has[i] == has[j]) ans[i][j] = 3;
      else ans[i][j] = 2;
    }
  for (int i = 1; i <= n; i++)
    for (int j = i + 1; j <= n; j++)
      if (ans[i][j] > 0) Ans += ans[i][j];
  cout << Ans << endl;
  return 0;
}
BZOJ 4435: [Cerc2015]Juice Junctions tarjan 4435: [Cerc2015]Juice Junctions Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 168  Solved: 77 [Submit][Status][Discuss] Description 你被雇佣升级一个旧果汁加工厂的橙汁运输系统。系统有管道和节点构成。每条管道都是双向的,且每条管道的流量都是1升每秒。 阅读详情

相关推荐

BZOJ 3590 [双连通分量][状压DP]

DescriptionDescription求一个包含所有节点的边双联通分量,并是边权和最小。n≤12n \le 12SolutionSolution注意到任意的一个边双连通分量都是由一条链和一个子双连通分量构成的,而且题中节点数n≤12n\le 12。考虑状压DP。令fSf_S表示点集为SS的双联通分量的权值的最小值。令hS,u,0/1h_{S, u, 0/1}表示边(u,v)(v∈S)(u,v)

Vectorxj的博客 589

BZOJ 1718 浅谈边双连通分量tarjan求法

世界真的很大 这几天学数论,算几,人都学傻了,什么FFT,高消的,会了有什么用呢?还不是死在没开long long上 这几天的亲身经历。。。 赶快做几道图论压压惊 看题先: description:In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to a

BerryKanry的博客 1190

BZOJ - 2574】[Poi1999] Store-Keeper(点双连通分量,求割点,记忆化bfs)

题干: 有一个仓库被分成n*m个矩形区域,如果两个区域有一条公共边,则被认为这两个区域相邻。包裹都放在一个区域中,剩余的区域或者空闲或者被集装箱占有,这是因为集装箱太重,仓库管理员不能将集装箱搬走。仓库管理员目是是要将包裹从开始的P区域移动到最后的K区域。他可以从空区域走到与之相邻的一个空区域。当仓库管理员走到与包裹相邻的区域时,它可以推动包裹,具体的推动方法如下所示: 读入一个储藏表...

xuanweiace的博客 914

bzoj1718(边双连通分量+贪心)

就是加点使图变成一个大的边双 先根据已有的边双缩点 会形成一棵树 贪心连叶子结点 答案=(num+1)/2(num+1)/2(num+1)/2 #include&amp;amp;lt;bits/stdc++.h&amp;amp;gt; using namespace std; int n , m , linkk[5100] ,t; int dfn[5100] , low[5100] , tt; int color[...

a1035719430的博客 662

[边双连通分量 Hash] BZOJ 4435 [Cerc2015]Juice Junctions

是不是只有我以为这是最小割树裸题 然后SB地大力分治跑最小割因为一个点度数不超过3 那么答案就是 0 1 2 3 先不在一个连通块的是0 在一个连通块但不在同一个边双里的是1然后怎么分辨 2 和 3 为2当且仅当存在删去某一条边 两个点不在同一个点双里 为3 也就是两个点所在的点双完全一样 我们尝试删除每条边 然后hash一下就好了#include<cstdio> #include<cst

雯舞 736

[BZOJ4435][连通性][hash][最小割树]Cerc2015:Juice Junctions

BZOJ4435 两点间的最大流只可能是0,1,2,3 如果是0,表示它们不连通 如果是1,表示它们连通,且处于不同的边双连通分量中 如果是2,表示它们处于同一个边双联通分量中 如果是3,表示如果任意删去一条边,它们仍在同一个边双联通分量中,hash判重即可 还可以最小割树,但是卡Dinic和ISPA,需要用KM Code: #include<bits/stdc++.h> #defin...

romiqi 255

BZOJ4435】[Cerc2015]Juice Junctions Tarjan+hash

BZOJ4435】[Cerc2015]Juice Junctions Description 你被雇佣升级一个旧果汁加工厂的橙汁运输系统。系统有管道和节点构成。每条管道都是双向的,且每条管道的流量都是1升每秒。管道可能连接节点,每个节点最多可以连接3条管道。节点的流量是无限的。节点用整数1到n来表示。在升级系统之前,你需要对现有系统进行分析。对于两个不同节点s和t,s-t的流量被定义为:...

weixin_30906701的博客 86

[BZOJ4435][Cerc2015]Juice Junctions

bzoj luogu description 给你一张\(n\)点\(m\)条边的无向图,保证每个点的度数不超过\(3\)。每条边容量为\(1\),求所有点对之间的最大流之和。 \(n\le3000,m\le4500\) sol 据说这题可以用最小割树跑过去。。。\(\mbox{orz}\) 考虑一些靠谱一点的算法。因为最大流等于最小割,而一个点的度数不超过\(3\),所以任意两点之间的...

abcyan1235的博客 177

【CERC2015】【BZOJ4435】Juice Junctions

Description你被雇佣升级一个旧果汁加工厂的橙汁运输系统。系统有管道和节点构成。每条管道都是双向的,且每条管道的流量都是1升每秒。管道可能连接节点,每个节点最多可以连接3条管道。节点的流量是无限的。节点用整数1到n来表示。在升级系统之前,你需要对现有系统进行分析。对于两个不同节点s和t,s-t的流量被定义为:当s为源点,t为汇点,从s能流向t的最大流量。以下面的第一组样例数据为例,1-6的流

CreationAugust is 14 years old forever 1413

bzoj2208 [Jsoi2010] 连通数(tarjan点双连通分量 // dfs)

题干: 题解:   本题也就是 一个有向图,题干中也没有说是否有环,我们就需要tarjan缩一下点(有向图缩点需要判断是否在队中),再进行操作。 100% 7000ms   dfs暴搜。枚举1~n 不断 dfs 求子树大小,统计答案。 Co...

anchengao1503的博客 206

【Tarjan】【强连通分量】 BZOJ 5201 —— Connections

题目传送门(没有权限号打不开) 对于每一个节点,我们保留一条树边,以及最多一条返祖边.注意这条返祖边要指向尽可能高的位置.这样下来保留的边数一定小于等于2n,并且满足图依旧是强连通的.至于为什么,贪心的想一想.既然之前满足强连通,我们保留走到dfn最小的返祖边后也一定是强连通的.最后随意乱加边直到2n即可. 只需进行一次Tarjan,保留树边,并在过程中维护出当前点通过返祖边走向的dfn最小的点,...

蒟蒻该待的地方 300

bzoj 5201】Connections(强连通分量)

传送门biu~ 只要跑一边Tarjan,记录选择了哪些树边和返祖边就好了。因为对于每个点,所选的与这个点相连的边的数量不会超过2,所以最终选择的边数一定少于2n。最后随便加边使边数到达2n即可。 ps.因为最后整个图也一定是强连通图,所以在Tarjan的时候完全不用stack和low[]。随便拿个dfn[]搞搞就可以了。 #include&lt;bits/stdc++.h&gt; #defi...

zP1nG 520

BZOJ 3590 Quare [状压DP][边双连通分量][点双联通分量]

题目传送门题目意思就是在一个无向图内求一个权值最小的且包含所有点的双联通子图。 DP乱搞,拆边双联通成链,与下一个子问题。状态压缩选择边的情况。貌似写了很多无用的DP。。。毕竟最后AC时我都不明觉厉。。 这种DP+图论神题还是少做吧,要夭寿的。 推荐这篇blog#include<queue> #include<cstdio> #include<cstring> #include<iostrea

lemonoil的博客 798

BZOJ3590】[Snoi2013]Quare【双连通分量】【状压DP】【神题】

【题目链接】 orz凯爷,见【Lethelody的题解】 首先一个双连通图可以拆为一个小双连通图和一条链。 设c[s][u][v]表示一条链的集合状态为s,链的端点分别为u和v的最短路径。 设h[s][u][0/1]表示集合状态为s,不在集合s内的点u与另一个在集合s中的点的最短路径/次短路径。 设f[s]表示集合状态为s,且s双联通的最小权值。 c可以递推转移。h

BraketBN 1389

Juice Junctions

Juice Junctions  Juice Junctions 题目描述   你被雇佣升级一个旧果汁加工厂的橙汁运输系统。系统有管道和节点构成。每条管道都是双向的,且每条管道的流量都是11升每秒。管道可能连接节点,每个节点最多可以连接33条管道。节点的流量是无限的。节点用整数11到nn来表示。在升级系统之前...

liankewei的博客 211

BZOJ 1123 [POI2008]BLO 点双连通分量

BZOJ 1123 [POI2008]BLO 点双连通分量

-Claude 1918

bzoj1718[Usaco2006 Jan] Redundant Paths 分离的路径 边双连通分量

这题想到一半了,最后缩点以后的统计答案挂了= =。。。 题意就不说了,问你加入多少条边能使得所有边都是一个边双。 n有点小了,怀疑有n^2水法。 求出边双以后缩点比较显然,然后我就有点蒙逼了,不知道怎么统计答案。。 想了dp和二分等奇怪姿势,然而好像都没用。 后来看了一波题解才发现是结论= =一棵树,要让他任意两点之间有超过1条路径相连,答案是(叶子节点个数+1)/2。 为啥呢?因为,一

老臣 687

[LCT 边双连通分量缩点] BZOJ 2959 长跑

一个边双连通分量肯定可以定向成一个环 那么就缩点 每次连接 要是本来不连通 就连起来 连通的话就把树上路径全缩起来 询问就是树上路径的值 #include #include #include #include #include #include using namespace std; typedef pair abcd; typ

雯舞 654

BZOJ4435】【Cerc2015】Juice Junctions

【题目链接】 点击打开链接 【思路要点】 建出GomoryHu-Tree ,剩余部分用DFS即可解决。 时间复杂度O(N∗Dinic(N,M)+N2)O(N∗Dinic(N,M)+N2)O(N*Dinic(N,M)+N^2),由于最大流至多为3,因此Dinic(N,M)=O(N+M)Dinic(N,M)=O(N+M)Dinic(N,M)=O(N+M)。 ...

cz_xuyixuan的博客 441
上一篇: BZOJ 4025 [并查集][二分图][分治]
下一篇: BZOJ 3590 [双连通分量][状压DP]
Vectorxj
博客等级 码龄10年 35粉丝 231原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值