小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点\(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. HACK字体安装

    参考:https://github.com/source-foundry/Hack Linux的 下载最新版本的Hack. 从存档中提取文件(.zip). 将字体文件复制到系统字体文件夹(通常/usr ...

  2. 各种 on事件触发js代码

    [转]各种 on事件触发js代码 1.onmouseenter:当鼠标进入选区执行代码 <div style="background-color:red" onmouseen ...

  3. docker使用自定义镜像zabbix服务

    一.关闭firewall,永久关闭,使用iptables防火墙 systemctl stop firewalld.service #停止firewall systemctl disable firew ...

  4. 62.Xcode 添加代码块

    1. Xcode创建一个新项目,打开一个.h或者.m文件 2.我举例以设置属性为例 #import <UIKit/UIKit.h> @interface ViewController : ...

  5. 关于java项目中的XML文件

    一,xml的机制 1.xml文件会在服务器启动的时候进行加载 2.加载完成后根据xml文件里面配置的属性对集成的对象进行属性和行为赋予 3.xml会有很多不同的标签,每个标签都有它特定的含义 二.为什 ...

  6. 查看mysql数据库中的所有用户

    SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM mysql.user; @前面为用户名,后面对应的‘% ...

  7. MFC随笔

    设置映射模式  Y轴改为向上 dc.SetMapMode(MM_LOENGLISH);//低精度 dc.SetMapMode(MM_HIENGLISH);//高精度 文本对齐 dc.SetTextAl ...

  8. excel的小bug

    http://muchong.com/html/201710/3913047.html Excel也有相同现象,试着计算:exp(-1.5^2),exp(0-1.5^2),exp(-(1.5)^2)看 ...

  9. Kotlin零碎总结

    1.对于Kotlin的包方法其实对应Java而言是静态方法,如Entrance.kt文件的外部有fun main(...方法,那么编译成字节码后就是Java的Entrance类里有public sta ...

  10. 强大的DataGrid组件[1]

    说明:DataGrid组件是Silverlight数据组件中最为常用并且是功能最为强大的数据组件.因此,对开发者而言,深入了解其特性是十分有必要的.本文先介绍该组件的基本特性,接着通过几个简单实例来说 ...