题目描述

小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话:

对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点 s 和 t 不在同一个部分中,则称这个划分是关于 s,t 的割。对于带权图来说,将所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而 s,t的最小割指的是在关于 s,t的割中容量最小的割。

现给定一张无向图,小白有若干个形如“图中有多少个无序点对的最小割的容量不超过 x ”的疑问,小蓝虽然很想回答这些问题,但小蓝最近忙着挖木块,于是作为小蓝的好友,你又有任务了。

输入格式

本题有多组测试数据。

第一行一个整数 T,表示测试数据组数。

对于每组测试数据,第一行两个整数 n,m,表示图的点数和边数。

接下来 m 行,每行三个整数 u,v,c表示有一条权为 ccc 的无向边 (u,v)。不保证图中无重边。

接下来一行一个整数 q 表示询问的个数,下面 q 行每行一个整数 x 描述一组询问。

输出格式

对于每一组测试数据输出 q 行,每行一个整数表示对应询问的答案。对于满足条件的点对 (p,q)和点对 (q,p) 只应该在答案中统计一次。

在两组测试数据之间需要输出一行空行。

输入输出样例

输入 #1

1

5 0

1

0

输出 #1

10

说明/提示

对于 100 的数据,1≤T≤10 ,1≤n≤150,0≤m≤30000,$$1 \leq x \leq 2^{31} - 1 $$ ,0≤q≤300

题解

最小割树(或者就是分治) , 每次选出两个点求出他们的最小割 , 在用这个值更新两边的最小割。

这题不难 , 但我还是调了好久(人话:我好弱啊!!!)

注意

1.题里给的是无向图 , 要建双向边 , 网络流如果要建双向边就不用对每个边再建那流量为0的边了。

2.\(ans[i][j]\) 更新时 \(ans[j][i]\) 也得更新啊!!

3.多测清空。

4.每组数组做完之后要输出回车

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
const int N = 1005 , M = 100100 , inf = 2e9;
inline int read()
{
register int x = 0 , f = 0; register char c = getchar();
while(c < '0' || c > '9') f |= c == '-' , c = getchar();
while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
return f ? -x : x;
}
int n , m , S , T , cnt = 1;
int d[N] , vis[N] , head[N] , ans[N][N] , t1[N] , t2[N] , a[N];
struct edge{ int v , nex , c; } e[M];
inline void add(int u , int v , int c) { e[++cnt].v = v; e[cnt].nex = head[u]; e[cnt].c = c; head[u] = cnt; e[++cnt].v = u; e[cnt].nex = head[v]; e[cnt].c = c; head[v] = cnt; return ; } queue<int> q;
bool bfs()
{
memset(d , 0 , sizeof d); d[S] = 1; q.push(S);
while(q.size())
{
int x = q.front(); q.pop();
for(int i = head[x] , v; i ; i = e[i].nex)
{
v = e[i].v; if(d[v] || e[i].c == 0) continue;
d[v] = d[x] + 1; q.push(v);
}
}
return d[T] != 0;
} int dfs(int x , int flow)
{
if(x == T || flow == 0) return flow;
int res = 0 , k;
for(int i = head[x] , v; i ; i = e[i].nex)
{
v = e[i].v; if(e[i].c == 0 || d[v] != d[x] + 1) continue;
k = dfs(v , min(e[i].c , flow));
if(k)
{
e[i].c -= k; e[i^1].c += k; res += k; flow -= k;
if(flow == 0) return res;
}
else d[v] = 0;
}
return res;
} int Dinic()
{
for(int i = 2 ; i <= cnt ; i += 2) e[i].c = e[i^1].c = (e[i^1].c + e[i].c) >> 1;
int ans = 0 , flow;
while(bfs()) while(flow = dfs(S , inf)) ans += flow;
return ans;
} void dfs(int x)
{
vis[x] = 1;
for(int i = head[x] ; i ; i = e[i].nex)
if(e[i].c && !vis[e[i].v]) dfs(e[i].v);
return ;
} void calc(int l , int r)
{
if(l >= r) return ;
memset(vis , 0 , sizeof vis);
S = a[l]; T = a[r]; int flow = Dinic() , cnt1 = 0 , cnt2 = 0; dfs(S);
for(int i = 1 ; i <= n ; ++i) if(vis[i]) for(int j = 1 ; j <= n ; ++j) if(!vis[j]) /*!!!!!!!!!!*/ ans[j][i] = ans[i][j] = min(ans[i][j] , flow);
for(int i = l ; i <= r ; ++i) if(vis[a[i]]) t1[++cnt1] = a[i]; else t2[++cnt2] = a[i];
for(int i = 1 ; i <= cnt1 ; ++i) a[l + i - 1] = t1[i];
for(int i = 1 ; i <= cnt2 ; ++i) a[l + i + cnt1 - 1] = t2[i];
calc(l , l + cnt1 - 1); calc(l + cnt1 , r);
return;
} int solve()
{
n = read(); m = read();
for(int i = 1 , u , v , c ; i <= m ; ++i) u = read() , v = read() , c = read() , add(u , v , c);
for(int i = 1 ; i <= n ; ++i) a[i] = i; memset(ans , 0x3f , sizeof ans);
calc(1 , n);
int Q = read();
while(Q--)
{
int x = read() , res = 0;
for(int i = 1 ; i <= n ; ++i) for(int j = i + 1 ; j <= n ; ++j) if(ans[i][j] <= x) res++;
cout << res << '\n';
}
memset(head , 0 , sizeof head); cnt = 1;
return 0;
} signed main()
{
// freopen("10.in" , "r" , stdin);
int T = read();
while(T --) solve() , cout << '\n';
return 0;
}
/*
2
5 0
1
0
5 0
1
0
*/

P3329 [ZJOI2011]最小割的更多相关文章

  1. BZOJ 2229 / Luogu P3329 [ZJOI2011]最小割 (分治最小割板题)

    题面 求所有点对的最小割中<=c的数量 分析 分治最小割板题 首先,注意这样一个事实:如果(X,Y)是某个s1-t1最小割,(Z,W)是某个s2-t2最小割,那么X∩Z.X∩W.Y∩Z.Y∩W这 ...

  2. BZOJ2229: [Zjoi2011]最小割

    题解: 真是一道神题!!! 大家还是围观JZP的题解吧(网址找不到了...) 代码: #include<cstdio> #include<cstdlib> #include&l ...

  3. 【BZOJ2229】[ZJOI2011]最小割(网络流,最小割树)

    [BZOJ2229][ZJOI2011]最小割(网络流,最小割树) 题面 BZOJ 洛谷 题解 戳这里 那么实现过程就是任选两点跑最小割更新答案,然后把点集划分为和\(S\)联通以及与\(T\)联通. ...

  4. bzoj千题计划139:bzoj2229: [Zjoi2011]最小割

    http://www.lydsy.com/JudgeOnline/problem.php?id=2229 最小割树介绍:http://blog.csdn.net/jyxjyx27/article/de ...

  5. [ZJOI2011]最小割 & [CQOI2016]不同的最小割 分治求最小割

    题面: [ZJOI2011]最小割 [CQOI2016]不同的最小割 题解: 其实这两道是同一道题.... 最小割是用的dinic,不同的最小割是用的isap 其实都是分治求最小割 简单讲讲思路吧 就 ...

  6. 【BZOJ2229】[Zjoi2011]最小割 最小割树

    [BZOJ2229][Zjoi2011]最小割 Description 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有 ...

  7. bzoj2229: [Zjoi2011]最小割(分治最小割+最小割树思想)

    2229: [Zjoi2011]最小割 题目:传送门 题解: 一道非常好的题目啊!!! 蒟蒻的想法:暴力枚举点对跑最小割记录...绝对爆炸啊.... 开始怀疑是不是题目骗人...难道根本不用网络流?? ...

  8. 【洛谷P3329】 [ZJOI2011]最小割(最小割树)

    洛谷 题意: 给出一个无向图,之后有\(q,q\leq 30\)组询问,每组询问有一个\(x\),回答有多少点对\((a,b)\)其\(a-b\)最小割不超过\(x\). 思路: 这个题做法要最小割树 ...

  9. [bzoj2229][Zjoi2011]最小割_网络流_最小割树

    最小割 bzoj-2229 Zjoi-2011 题目大意:题目链接. 注释:略. 想法: 在这里给出最小割树的定义. 最小割树啊,就是这样一棵树.一个图的最小割树满足这棵树上任意两点之间的最小值就是原 ...

随机推荐

  1. docker部署带mysql数据库连接的.netcore程序

    docker部署带mysql数据库连接的程序和部署普通的程序完全一致 数据库可以是物理机删的mysql,同时也可以是docker里的mysql. 如果是docker中的mysql,配置连接字符串和物理 ...

  2. RxHttp 让你眼前一亮的Http请求框架

    1.前言 RxHttp在今年4月份一经推出,就受到了广大Android 开发者的喜爱,截止本文发表在github上已有1100+star,为此,我自己也建个RxHttp&RxLife 的群(群 ...

  3. Spring Bean自动装配有哪些方式?

    Spring 容器能够自动装配 Bean .也就是说,可以通过检查 BeanFactory 的内容让 Spring 自动解析 Bean 的协作者. 自动装配的不同模式: no - 这是默认设置,表示没 ...

  4. Oracle查询如何才能行转列?-sunziren

    原创文章,转载务必注明出处. 今天工作的时候,碰到一个问题,涉及oracle行转列,用了半小时解决,因此在这里写个博客记录一下解决办法. 原数据库表的数据是: 想要达到的效果是: 经过思考,这是一个o ...

  5. js的reduce累加器

    reduce为数组中每一个元素执行回调函数,不包括被删除或未被赋值的 https://www.jianshu.com/p/e375ba1cfc47

  6. junit 常用注解 + junit 断言详解

    @Test: 在junit3中,是通过对测试类和测试方法的命名来确定是否是测试,且所有的测试类必须继承junit的测试基类.在junit4中,定义一个测试方法变得简单很多,只需要在方法前加上@Test ...

  7. 洛谷P1063能量项链(区间dp)

    题目描述: 给定一串序列x[],其中的每一个Xi看作看作一颗珠子,每个珠子包含两个参数,head和tail,前一颗的tail值是后一个的head值,珠子呈现环形(是一条项链),所以最后一颗的tail是 ...

  8. 【WCF Restful】Post传参示范

    1.传多个参数 接口定义:(ResponseFormat与RequestFormat分别将相应参数序列化.请求参数反序列化) [OperationContract] [WebInvoke(UriTem ...

  9. python文件操作汇总day7

    Python处理文件 文件操作分为读.写.修改,我们先从读开始学习 读文件 示例1: f = open(file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt',mode='r',enc ...

  10. 剑指offer-面试题46-把数字翻译成字符串-动态规划

    /* 题目: 给定一个数字,将0~25依次翻译为a~z,计算有多少种翻译方法. */ /* 思路: 动态规划法 */ #include<iostream> #include<cstr ...