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 ...
随机推荐
- php 之 文件操作(0524)
php中文件包含两种:文件,文件夹.文件夹又称目录 新建一个文件aa.txt和一个文件夹text,text文件夹下又包含bb.txt 一.判断文件类型filetype("./aa.txt&q ...
- POJ1961 KMP算法
POJ1961 问题重述: 输入一个长度为l的字符串S,求所有S的由字串重复排列而成的前缀,并输出前缀的长度以及该前缀的最大重复度. AC代码: //Memory: 5700K Time: 641MS ...
- 常用meta标签整理
< meta > 元素 概要 标签提供关于HTML文档的元数据.元数据不会显示在页面上,但是对于机器是可读的.它可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 we ...
- Jetty9开发(1)
Version: 9.2.14.v20151106 Jetty : 开发文档 jetty的官网:http://www.eclipse.org/jetty/ Jetty : 开发文档 目录 I. je ...
- EasyUI datagrid简单运用
jquery的前端框架挺多的,有easyUI ,bootstrap...,对于做系统软件或许easyUI比较好,因为里面控件很丰富,而bootstrap非常简洁大方,但是控件相 对比较少,特别是复杂的 ...
- Android中半透明Activity效果另法
Android中的Activity有没有类似于像Windows程序样的窗口式显示呢? 答案当然是有. 下图就是一个窗口式Activity的效果图: 下面就说说实现过程: 首先看看AndroidMani ...
- ImageMagick提取图像原始数据(ImageData/RawData)
我用的是ImageMagickWand的接口,因为这接口比Core接口更上层,所以官方文档推荐用. 抽取整个图像文件字节数据: http://www.imagemagick.org/discourse ...
- C++基础回顾1(数据类型, 控制语句, 数组)
最近两天打开本科学校的C++教材,快速回顾了一下C++方面的内容.虽然书本内容比较基础,但是还是有些知识点值得自己强化记忆.分几篇文章,加上自己的理解记录如下. 先回顾面向过程的部分. C++数据类型 ...
- Exchange Server 2010/2013架构改变
Exchange Server 2010架构 Exchange Server 2013架构
- (step5.1.6)hdu 1272(小希的迷宫——并查集)
题目大意:输入一系列的点,判断这些点组成的图符不符合小希的思路(无环.连通) 解题思路: 1)如果两个节点的根节点相同,那么在这两个节点之间添加1条边以后,这个图肯定有环路. 2)孤立节点:被使用过& ...