题目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. 【转】char *str 和 char str[]的区别

    char str[] = "abcd";定义了一个局部字符数组,返回它的地址肯定是一个已经释放了的空间的地址. 此函数返回的是内部一个局部字符数组str的地址,且函数调用完毕后 此 ...

  2. 网络流初步——增广路算法(EK)模板

    #include <iostream> #include <queue> #include<string.h> using namespace std; #defi ...

  3. 利用css进行网页布局

    网页布局: 又称版式布局,是网页UI设计师将有限的视觉元素进行有机的排列组合,将理性的思维个性的化的表现出来,是一种具有个人艺术特色的视觉传达方式.传达信息的同时有美感.网页设计特点(相对纸媒来说). ...

  4. Intent系列讲解---Intent简介以及相关属性

    一.Intent简介 Intent中文是"意图,意向",它是Android中四大组件通讯的纽带,Intent负责对应用中一次操作的动作.动作涉及数据.附加数据进行描述,Androi ...

  5. 编译recovery及过程中的部分错误解决

    你必须使用32位或64位Ubuntu系统,关于如何建立编译环境和同步源码的指导,请自己查找有关指导的文章. 1, 安装所需要的包 2, 建立编译的环境,并同步CWM所需的源码,CyanogenMod源 ...

  6. Ubuntu12.04下载Android4.0.1源码全过程,附若干问题解决[转]

    学校里一直在做应用层开发,考虑到日后就业问题,这次决定研究源码和驱动,并进行编译.没想到就下载源码这一步折腾了我整整两天,期间遇到很多问题,哎,记录于此,希望日后再下源码的人不要再走无谓的弯路了.事实 ...

  7. Blogger安装最新文章 - Blog透视镜

    在Blogger中,是没有最新文章的网页元素,不过倒是有信息提供这个小工具,其实这就是用来新增RSS网摘用的,其中就包含最新文章的Feed,所以只要在小工具中,加入RSS网摘Feed,就可以安装最新文 ...

  8. Flume配置

    http://my.oschina.net/leejun2005/blog/288136#OSC_h1_1 http://blog.cloudera.com/blog/2012/09/analyzin ...

  9. LeetCode_Swap Nodes in Pairs

    Given a linked list, swap every two adjacent nodes and return its head. For example, Given 1->2-& ...

  10. HDU3564 --- Another LIS (线段树维护最值问题)

    Another LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...