P4214 [CERC2015]Juice Junctions 题解
最小割树板子题。
一开始我用通常我写的
后面尝试使用
最后题解区说可以用
好吧,
可为啥
思路#
应该没有人不会最小割树吧。
我觉得能找到这题的应该都会最小割树。
所以这里我可以对这道题网络流做法的迷惑的复杂度,做一些感性理解。
由于
故其网络流的最大复杂度应该为
故总复杂度应为
而
给
#include <bits/stdc++.h>
using namespace std;
const int N = 3010;
const int M = 20000;
const int inf = 1e9 + 7;
int T , n , m , s , t , q , cnt , maxflow;
int id[N] , que[N] , vis[N] , tmp[N] , head[N];
struct edge
{
int to , nxt , val , sum;
}e[M];
struct Pre
{
int v , edge;
}pre[N];
inline int read()
{
int asd = 0 , qwe = 1; char zxc;
while(!isdigit(zxc = getchar())) if(zxc == '-') qwe = -1;
while(isdigit(zxc)) asd = asd * 10 + zxc - '0' , zxc = getchar();
return asd * qwe;
}
inline void add(int x , int y , int z)
{
e[++cnt] = {y , head[x] , z , z} , head[x] = cnt;
e[++cnt] = {x , head[y] , 0 , 0} , head[y] = cnt;
}
inline int bfs()
{
queue<int> q;
memset(que , 0 , sizeof que);
memset(pre , -1 , sizeof pre);
q.push(s) , que[s] = 1;
while(q.empty() == 0)
{
int x = q.front(); q.pop();
for(int i = head[x];i;i = e[i].nxt)
if(que[e[i].to] == 0 && e[i].val)
{
que[e[i].to] = 1;
pre[e[i].to] = (Pre){x , i};
if(e[i].to == t) return 1;
q.push(e[i].to);
}
}
return 0;
}
inline void init()
{
for(int i = 0;i <= cnt;i++) e[i].val = e[i].sum;
}
inline int EK(int ss , int ts)
{
s = ss , t = ts , maxflow = 0 , init();
while(bfs())
{
int minn = inf;
for(int i = t;i != s;i = pre[i].v) minn = min(minn , e[pre[i].edge].val);
for(int i = t;i != s;i = pre[i].v) e[pre[i].edge].val -= minn;
maxflow += minn;
}
return maxflow;
}
struct GHT
{
edge tr[M];
int tot , hed[N] , ans[N][N];
inline void add_tree(int x , int y , int z)
{
tr[++tot] = {y , hed[x] , z} , hed[x] = tot;
tr[++tot] = {x , hed[y] , z} , hed[y] = tot;
}
inline void find(int now)
{
vis[now] = 1;
for(int i = head[now];i;i = e[i].nxt)
if(vis[e[i].to] == 0 && e[i].val) find(e[i].to);
}
inline void build(int l ,int r)
{
if(l >= r) return;
int x = id[l] , y = id[l + 1] , sum = EK(x , y);
int ls = l , rs = r;
memset(vis , 0 , sizeof vis) , find(x);
add_tree(x , y , sum);
for(int i = l;i <= r;i++)
tmp[(vis[id[i]] ? ls++ : rs--)] = id[i];
for(int i = l;i <= r;i++) id[i] = tmp[i];
build(l , ls - 1) , build(rs + 1 , r);
}
inline void get(int now , int fa , int dis , int gen)
{
ans[gen][now] = dis;
for(int i = hed[now];i;i = tr[i].nxt)
if(tr[i].to != fa) get(tr[i].to , now , min(dis , tr[i].val) , gen);
}
inline void solve()
{
for(int i = 1;i <= n;i++) id[i] = i;
build(1 , n);
for(int i = 1;i <= n;i++) get(i , 0 , inf , i);
}
inline int ask()
{
int res = 0;
for(int i = 1;i <= n;i++)
for(int j = i + 1;j <= n;j++) res += ans[i][j];
return res;
}
}tree;
int main()
{
n = read() , m = read() , cnt = 1;
for(int i = 1;i <= m;i++)
{
int x = read() , y = read();
add(x , y , 1) , add(y , x , 1);
}
tree.solve();
cout << tree.ask();
return 0;
}
作者:JiaY19
出处:https://www.cnblogs.com/JiaY19/p/15944941.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)