BZOJ2561 最小生成树 【最小割】
题目
给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?
输入格式
第一行包含用空格隔开的两个整数,分别为N和M;
接下来M行,每行包含三个正整数u,v和w表示图G存在一条边权为w的边(u,v)。
最后一行包含用空格隔开的三个整数,分别为u,v,和 L;
数据保证图中没有自环。
输出格式
输出一行一个整数表示最少需要删掉的边的数量。
输入样例
3 2
3 2 1
1 2 3
1 2 2
输出样例
1
提示
对于20%的数据满足N ≤ 10,M ≤ 20,L ≤ 20;
对于50%的数据满足N ≤ 300,M ≤ 3000,L ≤ 200;
对于100%的数据满足N ≤ 20000,M ≤ 200000,L ≤ 20000。
题解
跪了QAQ怎么想得到是网络流,如此之大的范围
我们首先思考一下想要该边加入最小生成树,那么要使得加入这条边时u,v不连通
想想最小生成树的kruskal算法,在长度L之前如果存在一条路径使得u,v联通,那么轮到L时必定无法加入最小生成树
所以我们单独抽出所有权值<L的边,删减若干边使得u,v不连通
这就用到了最小割
最大生成树类似
可以证明,时间复杂度是\(O(M^{1.5})\)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 20005,maxm = 1000005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int n,m;
struct EDGE{int to,nxt,f;};
struct node{int a,b,w;}e[maxm];
struct FLOW{
EDGE ed[maxm];
int h[maxn],ne,S,T,vis[maxn],d[maxn],cur[maxn];
void init(){memset(h,0,sizeof(h)); ne = 2;}
void build(int u,int v,int w){
ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v],0}; h[v] = ne++;
}
bool bfs(){
for (int i = 1; i <= n; i++) d[i] = INF,vis[i] = false;
queue<int> q;
q.push(S); d[S] = 0; vis[S] = true;
int u;
while (!q.empty()){
u = q.front(); q.pop();
Redge(u) if (ed[k].f && !vis[to = ed[k].to]){
d[to] = d[u] + 1; vis[to] = true;
q.push(to);
}
}
return vis[T];
}
int dfs(int u,int minf){
if (u == T || !minf) return minf;
int f,flow = 0,to;
if (cur[u] == -1) cur[u] = h[u];
for (int& k = cur[u]; k; k = ed[k].nxt)
if (d[to = ed[k].to] == d[u] + 1 && (f = dfs(to,min(minf,ed[k].f)))){
ed[k].f -= f; ed[k ^ 1].f += f;
flow += f; minf -= f;
if (!minf) break;
}
return flow;
}
int maxflow(){
int flow = 0;
while (bfs()){
memset(cur,-1,sizeof(cur));
flow += dfs(S,INF);
}
return flow;
}
}G;
int main(){
n = read(); m = read();
for (int i = 1; i <= m; i++)
e[i].a = read(),e[i].b = read(),e[i].w = read();
G.init();
G.S = read(); G.T = read();
int ans = 0,L = read();
for (int i = 1; i <= m; i++)
if (e[i].w < L){
G.build(e[i].a,e[i].b,1);
G.build(e[i].b,e[i].a,1);
}
ans += G.maxflow();
G.init();
for (int i = 1; i <= m; i++)
if (e[i].w > L){
G.build(e[i].a,e[i].b,1);
G.build(e[i].b,e[i].a,1);
}
ans += G.maxflow();
printf("%d\n",ans);
return 0;
}
BZOJ2561 最小生成树 【最小割】的更多相关文章
- BZOJ2561最小生成树——最小割
题目描述 给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最 ...
- 【BZOJ2561】最小生成树 最小割
[BZOJ2561]最小生成树 Description 给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在 ...
- 【BZOJ-2521】最小生成树 最小割
2521: [Shoi2010]最小生成树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 415 Solved: 242[Submit][Statu ...
- BZOJ 2561: 最小生成树(最小割)
U,V能在最小(大)生成树上,当且仅当权值比它小(大)的边无法连通U,V. 两次最小割就OK了. --------------------------------------------------- ...
- BZOJ2521:[SHOI2010]最小生成树(最小割)
Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法.另外,他还知道,某一个图可 ...
- BZOJ2521[Shoi2010]最小生成树——最小割
题目描述 Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法.另外,他还知道,某一个图可能有多种不同的 ...
- 【BZOJ2521】[Shoi2010]最小生成树 最小割
[BZOJ2521][Shoi2010]最小生成树 Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算 ...
- BZOJ2521 最小生成树 最小割
5.26 T2:最小生成树 Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法 ...
- BZOJ.2521.[SHOI2010]最小生成树(最小割ISAP/Dinic)
题目链接 一条边不变其它边减少可以看做一条边增加其它边不变. 假设要加的边lab为(A->B,v),那么肯定是要使除这条边外,A->B的每条路径上的最小权值都\(>v\),这样在连通 ...
- BZOJ 2521 最小生成树(最小割)
http://www.lydsy.com/JudgeOnline/problem.php?id=2521 题意:每次能增加一条边的权值1,求最小代价让一条边保证在最小生成树里 思路:如果两个点中有环, ...
随机推荐
- Spring下读取properties文件
由于在spring的xml文件中配置了 <bean id="validator" class="org.springframework.validation.bea ...
- java代码(生成long类型数字)
package test; public class GenerateNum { public static void main(String[] args) { //定义为long类型,需在数值后面 ...
- vue.js与react.js相比较的优势
vue.js的简介 vue.js是一个javascript mvvm库,它是以数据驱动和组件化的思想构建的.我们平时多用js去操作dom,vue.js则是使用了数据绑定驱动来操作dom的,也就是说创建 ...
- java动态代理使用详解
我们都知道AOP的原理就是java的动态代理机制,下面我就对java的动态代理机制进行学习与总结 java动态代理的实现有两个重要的类: Proxy:类 作用就是用来动态创建一个代理对象的类 Invo ...
- 使用Google Colab训练神经网络(二)
Colaboratory 是一个 Google 研究项目,旨在帮助传播机器学习培训和研究成果.它是一个 Jupyter 笔记本环境,不需要进行任何设置就可以使用,并且完全在云端运行.Colaborat ...
- Webpack2 视频教程
原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」.Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本 ...
- CPP-基础:友元
友元可以是一个函数,该函数被称为友元函数:友元也可以是一个类,该类被称为友元类. 我们已知道类具有封装和信息隐藏的特性.只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的.非成 ...
- shell脚本,如何监控mysql数据库。
[root@localhost wyb]# cat jkmysql #!/bin/bash status=`/etc/init.d/mysqld status|grep running|wc -l` ...
- iOS开发遇到的坑之三--使用asi框架在xcode下正常运行,但是打包时却不能进行网络访问
前言: 前两篇博客遇到的问题是前几天在实验室开发的时候遇到的,花了两三天时间在上面,今天突然心血来潮,想把这些”坑”写下来,所以才有了这两篇写的很丑的博客随笔 今天在开发时又遇到一个问题,那就是标题所 ...
- STL 之 vector的应用
关于vector vector是C++提供的一个容器,它是一个能够存放任意类型的动态数组,可以随时增加和压缩数据. 使用vector时需要注意以下几点: 1. 如果要表示的向量长度较长(需要为向量内部 ...