LoibreOJ 2042. 「CQOI2016」不同的最小割 最小割树 Gomory-Hu tree
2042. 「CQOI2016」不同的最小割
题目描述
学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点 s,ts, ts,t 不在同一个部分中,则称这个划分是关于 s,ts, ts,t 的割。对于带权图来说,将所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而 s,ts, ts,t 的最小割指的是在关于 s,ts, ts,t 的割中容量最小的割。
而对冲刺 NOI 竞赛的选手而言,求带权图中两点的最小割已经不是什么难事了。我们可以把视野放宽,考虑有 NNN 个点的无向连通图中所有点对的最小割的容量,共能得到 N(N−1)2 个数值。这些数值中互不相同的有多少个呢?这似乎是个有趣的问题。
输入格式
输入文件第一行包含两个数 N,MN, MN,M,表示点数和边数。
接下来 MMM 行,每行三个数 u,v,wu, v, wu,v,w,表示点 uuu 和点 vvv(从 111 开始标号)之间有一条权值是 www 的边。
输出格式
输出文件第一行为一个整数,表示不同的最小割容量的个数。
样例
样例输入
4 4
1 2 3
1 3 6
2 4 5
3 4 4
样例输出
3
数据范围与提示
Case # | NNN | MMM |
---|---|---|
1 | 252525 | 150150150 |
2 | 505050 | 500500500 |
3 | 100100100 | 100010001000 |
4 | 150150150 | 150015001500 |
5 | 200200200 | 200020002000 |
6 | 300300300 | 300030003000 |
7 | 400400400 | 400040004000 |
8 | 500500500 | 500050005000 |
9 | 700700700 | 700070007000 |
10 | 850850850 | 850085008500 |
对于所有测试点,w≤100000w \leq 100000w≤100000。
题目链接:https://loj.ac/problem/2042
题意:中文题目,意思很明显。就是求一个图以任意顶点作为s和t求有几种最小割。
思路:Gomory-Hu tree,表示图中所有s - t对的最小s - t切割的加权树。
Gomory-Hu tree建立的过程:
首先以1为根建立一颗菊花树
然后对于2到n每个节点:跑它(S)和它父亲(T)的最小割(初始时,每个点的父亲节点均是1)
得出来的最小割即为树上该条边的权值
然后找到比该节点编号大的节点,如果它的父亲为T且它在S集中(dinic后还能被增广到的点属于S集,即vis数组),那么把它的父亲置为S。
复杂度就是最小割*n
然后树上两点间路径的瓶颈即为两点间最小割。
(其实我也不知道为什么是这样)
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
#define PI acos(-1.0)
const int maxn=2e3+,maxm=1e5+,inf=0x3f3f3f3f,mod=1e9+;
const ll INF=1e18+;
struct edge
{
int from,to,cap,flow;
};
vector<edge>es;
vector<int>G[maxn];
bool vis[maxn];
int dist[maxn];
int iter[maxn];
void init(int n)
{
for(int i=; i<=n+; i++) G[i].clear();
es.clear();
}
void addedge(int from,int to,int cap)
{
es.push_back((edge)
{
from,to,cap,
});
es.push_back((edge)
{
to,from,,
});
int x=es.size();
G[from].push_back(x-);
G[to].push_back(x-);
}
bool BFS(int s,int t)
{
memset(vis,,sizeof(vis));
queue <int> Q;
vis[s]=;
dist[s]=;
Q.push(s);
while(!Q.empty())
{
int u=Q.front();
Q.pop();
for (int i=; i<G[u].size(); i++)
{
edge &e=es[G[u][i]];
if (!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=;
dist[e.to]=dist[u]+;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int u,int t,int f)
{
if(u==t||f==) return f;
int flow=,d;
for(int &i=iter[u]; i<G[u].size(); i++)
{
edge &e=es[G[u][i]];
if(dist[u]+==dist[e.to]&&(d=DFS(e.to,t,min(f,e.cap-e.flow)))>)
{
e.flow+=d;
es[G[u][i]^].flow-=d;
flow+=d;
f-=d;
if (f==) break;
}
}
return flow;
}
int Maxflow(int s,int t)
{
for(int i=; i<es.size(); i++) es[i].flow=;
int flow=;
while(BFS(s,t))
{
memset(iter,,sizeof(iter));
int d=;
while(d=DFS(s,t,inf)) flow+=d;
}
return flow;
}
int pa[maxn];
set<int>ans;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
init(n);
for (int i=; i<=m; i++)
{
int u,v,r;
scanf("%d %d %d",&u,&v,&r);
addedge(u,v,r);
addedge(v,u,r);
}
for(int i=; i<=n; i++) pa[i]=;
for(int u=; u<=n; u++)
{
int v=pa[u];
int flow=Maxflow(u,v);
//cout<<u<<" "<<v<<" "<<flow<<endl;
ans.insert(flow);
for(int j=u+; j<=n; j++)
if(pa[j]==v&&vis[j]) pa[j]=u;
}
printf("%d\n",ans.size());
return ;
}
最小割树
LoibreOJ 2042. 「CQOI2016」不同的最小割 最小割树 Gomory-Hu tree的更多相关文章
- bzoj 4519: [Cqoi2016]不同的最小割【最小割树Gomory–Hu tree】
算法详见:http://www.cnblogs.com/lokiii/p/8191573.html 求出点两两之间的最小割之后,把他们扔到map/set里跑即可 可怕的是map和set跑的时间竟然完全 ...
- 最小割树Gomory–Hu tree
fanhq666地址:http://fanhq666.blog.163.com/blog/static/8194342620113495335724/ wiki地址(证明):https://en.wi ...
- LibreOJ2042 - 「CQOI2016」不同的最小割
Portal Description 给出一个给出一个\(n(n\leq850)\)个点\(m(m\leq8500)\)条边的无向图.定义\(cut(s,t)\)等于\(s,t\)的最小割的容量,求在 ...
- 「CQOI2016」不同的最小割
「CQOI2016」不同的最小割 传送门 建出最小割树,把每一个点对的最小割抠出来 \(\text{unique}\) 一下就好了. 参考代码: #include <algorithm> ...
- loj #2044. 「CQOI2016」手机号码
#2044. 「CQOI2016」手机号码 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- LibreOJ2044 - 「CQOI2016」手机号码
Portal Description 给出两个十一位数\(L,R\),求\([L,R]\)内所有满足以下两个条件的数的个数. 出现至少\(3\)个相邻的相同数字: 不能同时出现\(4\)和\(8\). ...
- LibreOJ2043 - 「CQOI2016」K 远点对
Portal Description 给出平面上的\(n(n\leq10^5)\)个整点,求在欧几里得距离下第\(k\)远的点对之间的距离. Solution k-d树+堆. 用小根堆维护当前找到的第 ...
- LibreOJ2045 - 「CQOI2016」密钥破解
Portal Description 给出三个正整数\(e,N,c(\leq2^{62})\).已知\(N\)能表示成\(p\cdot q\)的形式,其中\(p,q\)为质数.计算\(r=(p-1)( ...
- LOJ #2359. 「NOIP2016」天天爱跑步(倍增+线段树合并)
题意 LOJ #2359. 「NOIP2016」天天爱跑步 题解 考虑把一个玩家的路径 \((x, y)\) 拆成两条,一条是 \(x\) 到 \(lca\) ( \(x, y\) 最近公共祖先) 的 ...
随机推荐
- php支付宝接口 的使用
下载地址(java/php都有) https://doc.open.alipay.com/doc2/detail?treeId=66&articleId=103571&docType= ...
- create-react-app之proxy
[create-react-app之proxy] create-react-app可以用于一键创建web_client环境,默认使用webpack-dev-server.但在开发过程中,往往需要cli ...
- session of express
[session of express] 1.express-session 一个提供session功能库 npm install express-session --save var session ...
- Python全栈开发 列表, 元组 数据类型知识运用及操作 range知识
一.列表 1.什么是列表? 列表是一个可变类型,由 [ ] 表示,每一项元素用逗号隔开.列表能够装大量的数据,可以装对象的对象. 2.列表的索引和切片. 列表和字符串一样,也有索引和切片.只不过列表 ...
- jdbctemplate 批量插入
public void batchImport(List<Map<String, Object>> list) { String sql = "insert into ...
- springboot 取消post数据大小限制
参考 https://blog.csdn.net/kkgbn/article/details/52088068 application.properties 添加 server.tomcat.max- ...
- centos openvpn 安装
安装环境: 系统:centos 6.5 openvpn:openvpn-2.2.1 lzo:lzo-2.09 下载地址:http://www.oberhumer.com/opensource/l ...
- 【资料整理】c#基础
.net基础:.net与C# .net是一个平台 c#是一门语言 .net的用途a.桌面应用程序 b.网站应用程序 c.专业游戏开发(XBOX360) d.嵌入式设备软件开发 e.智能手机APP开发 ...
- JS中DOM以及BOM
一.bom对象 1screen对象 console.log(screen.width);// 屏幕宽度 console.log(screen.height);// 屏幕高度 console.log(s ...
- PHP序列及反序列化安全漏洞
尽量阐述全PHP序列化的相关东西-.- 1.序列化和反序列化 序列化是将变量或对象转换成字符串的过程:反序列化是将字符串转换成变量或对象的过程. 序列化及反序列化常见函数:serializ ...