题目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 不同的最小割 (最小割分治)的更多相关文章

  1. 最小割树(Gomory-Hu Tree)求无向图最小割详解 附 BZOJ2229,BZOJ4519题解

    最小割树(Gomory-Hu Tree) 前置知识 Gomory-Hu Tree是用来解决无向图最小割的问题的,所以我们需要了解无向图最小割的定义 和有向图类似,无向图上两点(x,y)的割定义为一个边 ...

  2. EBS oracle 批量导入更新MOQ(最小拆分量、采购提前期、最小订购量、最小包装量)

    EXCEL的列:组织id,供应商编号,供应商地点,料号,最小拆分量.采购提前期.最小订购量.最小包装量 --采购导入更新MOQ四个值,若有为空的那列,会保留原来的值,不会去更新那列的值 PROCEDU ...

  3. delphi中最小化其他程序及所有程序最小化(使用 shell.minimizeAll 和自己寻找窗口这两种办法)

    1.所有程序最小化 uses ComObj;   var    shell : OleVariant; begin      shell := CreateOleObject('Shell.Appli ...

  4. 最小正子序列(序列之和最小,同时满足和值要最小)(数据结构与算法分析——C语言描述第二章习题2.12第二问)

    #include "stdio.h" #include "stdlib.h" #define random(x) (rand()%x) void creat_a ...

  5. ACdream 1135(MST-最小生成树边上2个值,维护第一个最小的前提下让还有一个最小)

    F - MST Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatu ...

  6. 【BZOJ-4435】Juice Junctions 最小割树(分治+最小割)+Hash

    4435: [Cerc2015]Juice Junctions Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 20  Solved: 11[Submi ...

  7. HDU3870 Catch the Theves(平面图最小割转最短路)

    题目大概说给一个n×n的方格,边有权值,问从求(1,1)到(n,n)的最小割. 点达到了160000个,直接最大流不好.这题的图是平面图,求最小割可以转化成求其对偶图的最短路,来更高效地求解: 首先源 ...

  8. hiho 第116周,最大流最小割定理,求最小割集S,T

    小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? 小Ho:我记得!网络流就是给定了一张图G=(V,E),以及源点s和汇点t.每一条边e(u,v)具有容量c ...

  9. poj 1815 Friendship 字典序最小+最小割

    题目链接:http://poj.org/problem?id=1815 In modern society, each person has his own friends. Since all th ...

随机推荐

  1. nvm linux命令

    nvm alias default 0.12.10 nvm alias default 0.10.24 nvm list NVM_NODEJS_ORG_MIRROR=http://npm.taobao ...

  2. CSS中cursor的pointer 与 hand-备

    cursor:hand 与 cursor:pointer 的效果是一样,都像手形光标(在浏览器上时   鼠标会显示成 小手 ).但用FireFox浏览时才注意到使用cursor:hand在FireFo ...

  3. 怎么通过网站优化来增强SEO效果?

    真正好的网站优化不应该针对哪一个搜索引擎,而应该关注用户的需求.搜索引擎把这这用户指标权重提升,实际上也是希望把更多的精力集中在用户体验的提升上面.那么,这些用户指标应该怎样提升呢?方法多种多样,下面 ...

  4. Content-Disposition的使用方法

    一.作用: 1)希望某类或者某已知MIME类型的文件(比如:*.gif;*txt;*.htm)能够在访问时弹出"文件下载对话框" 2)希望客户端下载时以指定文件名显示 3)希望某文 ...

  5. 自定义Window进入和退出效果(转)

    看了android的源代码和资源文件,终于明白如何去修改设置Dialog和Activity的进入和退出效果了. 设置Dialog首先通过getWindow()方法获取它的窗口, 然后通过getAttr ...

  6. 在O(1) 时间删除链表节点

    struct Node { int val; Node * next; }; void deleteNode(Node ** head, Node * target) { assert(head != ...

  7. TVS管

    1.原理 TVS二极管在线路板上与被保护线路并联,当瞬时电压超过电路正常工作电压后,TVS二极管便产生雪崩,提供给瞬时电流一个超低电阻通路,其结果是瞬时电流透过二极管被引开,避开被保护元件,并且在电压 ...

  8. Qt编程之qrc文件的链接

    在Qt里面,.qrc文件是一种类似XML结构的文件,用结构化数据描述应用程序所需要的资源位置,例如图片,应用程序的图标文件等.它最终是与.ui文件类似都被通过Qt提供的命令行工具生成对应的qrc_XX ...

  9. 关于IoAttachDeviceToDeviceStack

    IoAttachDeviceToDeviceStack将Source Device附加到Target Device上. 打开windbgkd> u IoAttachDeviceToDeviceS ...

  10. Lucene 高亮功能

    原文转载自: http://qindongliang1922.iteye.com/blog/1953409 高亮功能一直都是全文检索的一项非常优秀的模块,在一个标准的搜索引擎中,高亮的返回命中结果,几 ...