小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点\(s,t\)不在同一个部分中,则称这个划分是关于\(s,t\)的割。 对于带权图来说,将所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而\(s,t\)的最小割指的是在关于\(s,t\)的割中容量最小的割” 现给定一张无向图,小白有若干个形如“图中有多少对点它们的最小割的容量不超过\(x\)呢”的疑问,小蓝虽然很想回答这些问题,但小蓝最近忙着挖木块,于是作为仍然是小蓝的好友,你又有任务了。

Input

输入文件第一行有且只有一个正整数T,表示测试数据的组数。 对于每组测试数据, 第一行包含两个整数\(n,m\),表示图的点数和边数。 下面\(m\)行,每行3个正整数\(u,v,c(1<=u,v<=n,0<=c<=10^6)\),表示有一条权为\(c\)的无向边\((u,v)\) 接下来一行,包含一个整数\(q\),表示询问的个数 下面\(q\)行,每行一个整数\(x\),其含义同题目描述。

Output

对于每组测试数据,输出应包括\(q\)行,第\(i\)行表示第\(i\)个问题的答案。对于点对\((p,q)\)和\((q,p)\),只统计一次(见样例)。

两组测试数据之间用空行隔开。

Sample Input

1
5 0
1
0

Sample Output

10

Hint

对于100%的数据 \(T<=10,n<=150,m<=3000,q<=30\),\(x\)在32位有符号整数类型范围内。

图中两个点之间可能有多条边

题意:

中文题面,不解释

题解:

最小割树求出所有的最小割,放入一个数组里面,然后对于么一个询问二分就行了。

有一个坑点,就是每组数据处理完之后要额外输出一个空行。

#include<bits/stdc++.h>
#define re register
using namespace std;
const int N=300,M=10010;
const long long inf=1ll<<60;
int n,m,a[N];
long long ans[N][N];
int head[N],nxt[M],bian[M];
long long zhi[M];
int tot;
void init(){
tot=1;
memset(head,0,sizeof head);
}
void add(int x,int y,long long z){
tot++;bian[tot]=y;zhi[tot]=z;nxt[tot]=head[x];head[x]=tot;
tot++;bian[tot]=x;zhi[tot]=z;nxt[tot]=head[y];head[y]=tot;
}
void build(int m){
for(int i=1;i<=m;i++){
int x,y;
long long z;
scanf("%d%d%lld",&x,&y,&z);
add(x,y,z);
}
}
void rebuild(){
for(int i=1;i<=tot;i+=2){
zhi[i]=zhi[i^1]=(zhi[i]+zhi[i^1])/2;
}
}
int v[N];
void cut(int x){
v[x]=1;
for(int i=head[x];i;i=nxt[i]){
if(zhi[i]&&!v[bian[i]])cut(bian[i]);
}
}
int d[N];
queue<int>q;
bool bfs(int b,int e){
memset(d,0,sizeof(d));
while(!q.empty())q.pop();
q.push(b);d[b]=1;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i;i=nxt[i]){
if(zhi[i] && !d[bian[i]]){
q.push(bian[i]);
d[bian[i]]=d[x]+1;
if(bian[i]==e)return 1;
}
}
}
return 0;
}
long long dinic(int b,int e,int x,long long flow){
if(x==e)return flow;
long long rest=flow,k;
for(int i=head[x];i && rest;i=nxt[i]){
if(zhi[i] && d[bian[i]]==d[x]+1){
k=dinic(b,e,bian[i],min(rest,zhi[i]));
if(!k)d[bian[i]]=0;
zhi[i]-=k;
zhi[i^1]+=k;
rest-=k;
}
}
return flow-rest;
}
inline long long maxflow(int b,int e){
long long flow=0,maxflow=0;
while(bfs(b,e)){
while(flow=dinic(b,e,b,inf))maxflow+=flow;
}
return maxflow;
}
int b,e;
void solve(int l,int r){
if(l==r)return;
rebuild();
b=a[l],e=a[r];
re long long mincut=maxflow(b,e);
memset(v,0,sizeof v);
cut(b);
for(re int i=1;i<=n;++i){
if(!v[i])continue;
for(re int j=1;j<=n;++j){
if(v[j])continue;
ans[i][j]=ans[j][i]=min(ans[i][j],mincut);
}
}
re int cnt=l-1;
static int ls[N];
for(re int i=l;i<=r;++i){
if(v[a[i]]){
ls[++cnt]=a[i];
}
}
re int fj=cnt;
for(re int i=l;i<=r;++i){
if(!v[a[i]]){
ls[++cnt]=a[i];
}
}
for(re int i=l;i<=r;++i)a[i]=ls[i];
solve(l,fj);
solve(fj+1,r);
}
int main()
{
int b,e,Q,T;
cin>>T;
while(T--){
memset(ans,0x3f3f3f,sizeof ans);
scanf("%d%d",&n,&m);
init();
build(m);
for(int i=1;i<=n;++i){
a[i]=i;
}
solve(1,n);
scanf("%d",&Q);
static long long as[40010];
int js=0;
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
as[++js]=ans[i][j];
}
}
sort(as+1,as+js+1);
long long ask;
for(int i=1;i<=Q;++i){
scanf("%lld",&ask);
int mid=lower_bound(as,as+js+1,ask+1)-as;
while(mid>js||(as[mid]>ask&&mid))mid--;
printf("%d\n",mid);
}puts("");
}
}

最小割(zjoi2011,bzoj2229)(最小割树)的更多相关文章

  1. [ZJOI2011][bzoj2229] 最小割 [最小割树]

    题面 传送门 思路 首先我们明确一点:这道题不是让你把$n^2$个最小割跑一遍[废话] 但是最小割过程是必要的,因为最小割并没有别的效率更高的算法(Stoer-Wagner之类的?) 那我们就要尽量找 ...

  2. 【BZOJ2229】【ZJOI2011】最小割

    冷门知识点…… 原题: 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中 ...

  3. 【bzoj2229】[Zjoi2011]最小割 分治+网络流最小割

    题目描述 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分 ...

  4. 「ZJOI2011」最小割

    「ZJOI2011」最小割 传送门 建出最小割树,然后暴力计算任意两点之间最小割即可. 多组数据记得初始化. 参考代码: #include <algorithm> #include < ...

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

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

  6. 不同的最小割(cqoi2016,bzoj4519)(最小割树)

    学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成 两个部分,如果结点\(s,t\)不在同一个部分中,则称这个划分是关于\(s,t\)的割.对于带权图来说,将 所有顶 ...

  7. bzoj 1797: [Ahoi2009]Mincut 最小割【tarjan+最小割】

    先跑一遍最大流,然后对残量网络(即所有没有满流的边)进行tarjan缩点. 能成为最小割的边一定满流:因为最小割不可能割一半的边: 连接s.t所在联通块的满流边一定在最小割里:如果不割掉这条边的话,就 ...

  8. Destroying The Graph 最小点权集--最小割--最大流

    Destroying The Graph 构图思路: 1.将所有顶点v拆成两个点, v1,v2 2.源点S与v1连边,容量为 W- 3.v2与汇点连边,容量为 W+ 4.对图中原边( a, b ), ...

  9. 【poj3522-苗条树】最大边与最小边差值最小的生成树,并查集

    题意:求最大边与最小边差值最小的生成树.n<=100,m<=n*(n-1)/2,没有重边和自环. 题解: m^2的做法就不说了. 时间复杂度O(n*m)的做法: 按边排序,枚举当前最大的边 ...

随机推荐

  1. Java学习笔记:知识总结

    概述 1991年由sun公司开发的名称为Oak的语言,1994年更名为Java. JDK:Java Development Kit,Java的开发和运行环境,Java的开发工具和JRE. JRE:Ja ...

  2. CSS-弹性布局-动画-过渡

    1.弹性布局 1.项目的属性 该组属性只能设置在某项目元素上,只控制一个项目,是不影响容器以及其他项目的效果. 1.order 作用:定义项目的排列顺序,值越小,越靠近起点,默认值是0 取值:整数数字 ...

  3. 50.IOS上传APP问题

    更新版本的时候遇到几个问题 1.ERROR ITMS-90535: "Unexpected CFBundleExecutable Key. The bundle at 'Payload/di ...

  4. 2018.10.26 NOIP模拟 性感手枪(搜索)

    传送门 vis[x][y]vis[x][y]vis[x][y]记录这个点是否在之前被搜过,且被搜过的坐标是什么. 然后搜索的时候记录一个循环的下标和不循环的下标就行了. 代码

  5. google pay app权限使用说明

    android.permission.CAMERA. 个人中心使用头像时需要使用该权限. android.permission.READ_PHONE.获取用户DeviceId,作为用户单点登录唯一值.

  6. C# 中的委托(Delegate)

    委托(Delegate) 是存有对某个方法的引用的一种引用类型变量.引用可在运行时被改变. 委托(Delegate)特别用于实现事件和回调方法.所有的委托(Delegate)都派生自 System.D ...

  7. mysql 查询中文字段 没有结果的解决方法

    代码如下: $conn = new mysqli('localhost', 'root', '', 'excel');$sql = "select 中信一级行业 from excel gro ...

  8. SpringBoot2.0.2 Application调用的三种方式

    一.注解 @SpringBootApplication            点开查看源码是由多个注解合成的注解,其中主要的注解有:            @SpringBootConfigurati ...

  9. 2.2 数据的图形描绘以及处理(QQplot,归一化)

    QQplot 横坐标表示的是属性的其中一个测量值1,纵坐标表示另一个测量值2.散点是分位点.点的横纵坐标是这个测量值1和测量值2的分位点的取值. from scipy import stats fro ...

  10. vue的饿了么写作感受

    1.在重复使用的组件中,要把重复使用组件的需要在数据的请求的地方设置为在富组件中,通过props船只到子组件,这样在重复调用次组件的时候既可以很好的避免组件的值的冲突 2.getData的使用,把所有 ...