ZJOI 最小割 CQOI 不同的最小割 (最小割分治)
题目1 ZJOI 最小割
题目大意:
求一个无向带权图两点间的最小割,询问小于等于c的点对有多少。
算法讨论: 最小割 分治
代码:
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector> using namespace std;
const int N = 150 + 5;
const int M = 3000 + 5;
const int oo = 0x3f3f3f3f;
#define inf oo int n, m;
bool mark[N];
int a[N], tmp[N], ans[N][N]; struct Edge {
int from, to, cap, flow;
Edge(int u = 0, int v = 0, int c = 0, int f = 0) :
from(u), to(v), cap(c), flow(f) {}
}; struct Dinic {
int n, mm, s, t;
int dis[N], cur[N], que[N * 10];
bool vis[N];
vector <Edge> edges;
vector <int> G[N]; void clear() {
for(int i = 0; i <= n; ++ i) G[i].clear();
edges.clear();
} void add(int from, int to, int cap) {
edges.push_back(Edge(from, to, cap, 0));
edges.push_back(Edge(to, from, cap, 0));
mm = edges.size();
G[from].push_back(mm - 2);
G[to].push_back(mm - 1);
} bool bfs() {
int head = 1, tail = 1;
memset(vis, false, (n + 1) * sizeof (bool));
dis[s] = 0; vis[s] = true; que[head] = s;
while(head <= tail) {
int x = que[head];
for(int i = 0; i < (signed) G[x].size(); ++ i) {
Edge &e = edges[G[x][i]];
if(!vis[e.to] && e.cap > e.flow) {
vis[e.to] = true;
dis[e.to] = dis[x] + 1;
que[++ tail] = e.to;
}
}
++ head;
}
return vis[t];
} int dfs(int x, int a) {
if(x == t || a == 0) return a;
int flw = 0, f;
for(int &i = cur[x]; i < (signed) G[x].size(); ++ i) {
Edge &e = edges[G[x][i]];
if(dis[e.to] == dis[x] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) {
e.flow += f; edges[G[x][i] ^ 1].flow -= f; flw += f; a -= f;
if(a == 0) break;
}
}
return flw;
} int maxflow(int s, int t) {
this->s = s; this->t = t;
int flw = 0;
while(bfs()) {
memset(cur, 0, sizeof cur);
flw += dfs(s, oo);
}
return flw;
} void rebuild() {
for(int i = 0; i < (signed) edges.size(); ++ i)
edges[i].flow = 0;
} void dfs(int u) {
mark[u] = true;
for(int i = 0; i < (signed) G[u].size(); ++ i) {
Edge e = edges[G[u][i]];
if(!mark[e.to] && e.cap > e.flow) {
dfs(e.to);
}
}
}
}net; void Divide(int l, int r) {
if(l >= r) return;
net.rebuild();
int nowflow = net.maxflow(a[l], a[r]);
memset(mark, false, (n + 1) * sizeof (bool));
net.dfs(a[l]);
for(int i = 1; i <= n; ++ i)
if(mark[i])
for(int j = 1; j <= n; ++ j)
if(!mark[j])
ans[i][j] = min(ans[i][j], nowflow), ans[j][i] = ans[i][j];
int L = l, R = r;
for(int i = l; i <= r; ++ i)
if(mark[a[i]]) tmp[L ++] = a[i];
else tmp[R --] = a[i];
for(int i = l; i <= r; ++ i) a[i] = tmp[i];
Divide(l, L - 1); Divide(R + 1, r);//这不能二分一个Mid,因为S集和T集的大小不一定相同
} int main() {
int T, u, v, c, q;
scanf("%d", &T);
while(T --) {
net.clear();
scanf("%d%d", &n, &m); net.n = n;
for(int i = 1; i <= n; ++ i) a[i] = i;
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= n; ++ j) ans[i][j] = inf;
for(int i = 1; i <= m; ++ i) {
scanf("%d%d%d", &u, &v, &c);
net.add(u, v, c);
}
Divide(1, n);
scanf("%d", &q);
for(int i = 1; i <= q; ++ i) {
int tmp = 0;
scanf("%d", &c);
for(int u = 1; u <= n; ++ u) {
for(int v = u + 1; v <= n; ++ v) {
if(ans[u][v] <= c) {
++ tmp;
}
}
}
printf("%d\n", tmp);
}
puts("");
}
return 0;
}
题目2 CQOI2016 不同的最小割
题目大意:
求所有点对问不同的最小割数目。
算法讨论: 最小割 分治
和上面的一个题有区别么?
代码:
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <set> using namespace std;
const int N = 850 + 5;
const int M = 8500 + 5;
const int oo = 0x3f3f3f3f; int n, m;
int ans[N][N], tmp[N], a[N];
bool mark[N];
set <int> lts; struct Edge {
int from, to, cap, flow;
Edge(int u = 0, int v = 0, int cap = 0, int flow = 0):
from(u), to(v), cap(cap), flow(flow) {}
}; struct Dinic {
int n, m, s, t;
int dis[N], cur[N], que[N * 10];
bool vis[N];
vector <Edge> edges;
vector <int> G[N]; void add(int from, int to, int cap) {
edges.push_back(Edge(from, to, cap, 0));
edges.push_back(Edge(to, from, cap, 0));
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
} bool bfs() {
int head = 1, tail = 1;
memset(vis, false, (n + 1) * sizeof (bool));
dis[s] = 0; vis[s] = true; que[head] = s;
while(head <= tail) {
int x = que[head];
for(int i = 0; i < (signed) G[x].size(); ++ i) {
Edge &e = edges[G[x][i]];
if(!vis[e.to] && e.cap > e.flow) {
vis[e.to] = true;
dis[e.to] = dis[x] + 1;
que[++ tail] = e.to;
}
}
++ head;
}
return vis[t];
} int dfs(int x, int a) {
if(x == t || a == 0) return a;
int flw = 0, f;
for(int &i = cur[x]; i < (signed) G[x].size(); ++ i) {
Edge &e = edges[G[x][i]];
if(dis[e.to] == dis[x] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) {
e.flow += f; edges[G[x][i] ^ 1].flow -= f; a -= f; flw += f;
if(a == 0) break;
}
}
return flw;
} int maxflow(int s, int t) {
this->s = s; this->t = t;
int flw = 0;
while(bfs()) {
memset(cur, 0, sizeof cur);
flw += dfs(s, oo);
}
return flw;
} void rebuild() {
for(int i = 0; i < (signed) edges.size(); ++ i)
edges[i].flow = 0;
} void dfs(int u) {
mark[u] = true;
for(int i = 0; i < (signed) G[u].size(); ++ i) {
Edge e = edges[G[u][i]];
if(!mark[e.to] && e.cap > e.flow)
dfs(e.to);
}
}
}net; void Divide(int l, int r) {
if(l >= r) return;
net.rebuild();
int nowflow = net.maxflow(a[l], a[r]);
memset(mark, false, (n + 1) * sizeof(bool));
net.dfs(a[l]);
for(int i = 1; i <= n; ++ i)
if(mark[i])
for(int j = 1; j <= n; ++ j)
if(!mark[j])
ans[i][j] = min(ans[i][j], nowflow), ans[j][i] = ans[i][j];
int L = l, R = r;
for(int i = l; i <= r; ++ i)
if(mark[a[i]]) tmp[L ++] = a[i];
else tmp[R --] = a[i];
for(int i = l; i <= r; ++ i)
a[i] = tmp[i];
Divide(l, L - 1); Divide(R + 1, r);
} int main() {
int u, v, c;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++ i) {
scanf("%d%d%d", &u, &v, &c);
net.add(u, v, c);
}
for(int i = 1; i <= n; ++ i) a[i] = i;
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= n; ++ j) ans[i][j] = oo;
net.n = n;
Divide(1, n);
for(int i = 1; i <= n; ++ i) {
for(int j = i + 1; j <= n; ++ j) {
lts.insert(ans[i][j]);
}
}
printf("%d\n", lts.size());
return 0;
}
ZJOI 最小割 CQOI 不同的最小割 (最小割分治)的更多相关文章
- 最小割树(Gomory-Hu Tree)求无向图最小割详解 附 BZOJ2229,BZOJ4519题解
最小割树(Gomory-Hu Tree) 前置知识 Gomory-Hu Tree是用来解决无向图最小割的问题的,所以我们需要了解无向图最小割的定义 和有向图类似,无向图上两点(x,y)的割定义为一个边 ...
- EBS oracle 批量导入更新MOQ(最小拆分量、采购提前期、最小订购量、最小包装量)
EXCEL的列:组织id,供应商编号,供应商地点,料号,最小拆分量.采购提前期.最小订购量.最小包装量 --采购导入更新MOQ四个值,若有为空的那列,会保留原来的值,不会去更新那列的值 PROCEDU ...
- delphi中最小化其他程序及所有程序最小化(使用 shell.minimizeAll 和自己寻找窗口这两种办法)
1.所有程序最小化 uses ComObj; var shell : OleVariant; begin shell := CreateOleObject('Shell.Appli ...
- 最小正子序列(序列之和最小,同时满足和值要最小)(数据结构与算法分析——C语言描述第二章习题2.12第二问)
#include "stdio.h" #include "stdlib.h" #define random(x) (rand()%x) void creat_a ...
- ACdream 1135(MST-最小生成树边上2个值,维护第一个最小的前提下让还有一个最小)
F - MST Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatu ...
- 【BZOJ-4435】Juice Junctions 最小割树(分治+最小割)+Hash
4435: [Cerc2015]Juice Junctions Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 20 Solved: 11[Submi ...
- HDU3870 Catch the Theves(平面图最小割转最短路)
题目大概说给一个n×n的方格,边有权值,问从求(1,1)到(n,n)的最小割. 点达到了160000个,直接最大流不好.这题的图是平面图,求最小割可以转化成求其对偶图的最短路,来更高效地求解: 首先源 ...
- hiho 第116周,最大流最小割定理,求最小割集S,T
小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? 小Ho:我记得!网络流就是给定了一张图G=(V,E),以及源点s和汇点t.每一条边e(u,v)具有容量c ...
- poj 1815 Friendship 字典序最小+最小割
题目链接:http://poj.org/problem?id=1815 In modern society, each person has his own friends. Since all th ...
随机推荐
- javascript字符类型操作函数
//获取字符串的长度 String.prototype.getByteLength = function() { var bytes=0,i=0; for (; i<this.length; + ...
- Symfony2之创建一个简单的web应用
Symfony2——创建bundle bundle就像插件或者一个功能齐全的应用,我们在应用层上开发的应用的所有代码,包括:PHP文件.配置文件.图片.css文件.js文件等都会包含在bu ...
- 在Mac上使用Nginx和FastCGI部署Flask应用
最近在学习Flask,本文介绍一下如何部署Flask开发的应用,同时也学习一下Nginx的使用,这只是在Mac上的一个实验. 应用 这里使用的应用就是官方的文档中给出的Flaskr. 安装Nginx ...
- OCR中的倾斜矫正
电面中被问到了做的LPR,简单的介绍了下后又问到了关于如何矫正倾斜角的问题.答得比较含糊,所以今天来补充一下. 倾斜矫正的方法有很多种,包括基于Hough变换的矫正,基于字符投影的倾角矫正,常规线性角 ...
- 安装notepad++之后怎样在鼠标右键上加上Edit with notepad++
在鼠标右键上加入使用notepad++编辑 我们在安装完notepad++文本编辑器之后,在一个文本文件上右键有时候并没有出现"使用notepad++编辑的选项",我们可以通过简单 ...
- Visual Studio 启动加速
Who is locking my SQL database?|Deploy a database project with TFS Build Visual Studio 2012 running ...
- linux磁盘限额配置:quota命令
LINUX下也有类似WINDOWS NTFS所用的磁盘限额,用的是quota来实现通过rpm -q quota确定是否已安装用quota只能对patation做限额,要做到针对某个目录来做只能靠ln ...
- Google GFS文件系统深入分析
Google GFS文件系统深入分析 现在云计算渐成潮流,对大规模数据应用.可伸缩.高容错的分布式文件系统的需求日渐增长.Google根据自身的经验打造的这套针对大量廉价客户机的Google GFS文 ...
- C++ 中 struct和class 的区别
来自:http://hi.baidu.com/pengxiangbobin19890125/blog/item/b05586eee77300212df53411.html C++ prime 中 ...
- HLS直播和时移项目上线
兄弟姐妹们: 天翼视讯的高清HLS直播和时移项目上线,测试观看地址为:http://118.85.192.228/live/,同时支持移动终端和pc终端.移动终端支持ios client和androi ...