题目链接

传送门

思路

根据题目给定的边跑一边最大流,然后再在残留网络上跑\(tarjan\)。

对于每一条边有:

  • 如果它是非满边,那么它一定不是最小割集里面的边;
  • 如果\(c[u[i]] \not= c[v[i]]\),那么它可以是最小割集里面的边;
  • 如果\(c[u[i]] \not= c[v[i]]\)且\(c[u[i]]=c[s],c[v[i]=c[t]]\),那么它一定是最小割集里面的边。

详情可以看\(hzwer\)大佬的解释。

代码实现如下

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL; #define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0) const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 4000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL; int n, m, top, num, cnt, u, v, w;
int dfn[maxn], low[maxn], stc[maxn], vis[maxn], c[maxn]; struct Dinic {
queue<int> q;
int maxflow, tot, s, t;
int head[maxn], d[maxn];
void init() {
tot = maxflow = 0;
memset(head, -1, sizeof(head));
}
struct edge {
int u, v, w, next;
}ed[220007];
void add(int u, int v, int w) {
ed[tot].u = u;
ed[tot].v = v;
ed[tot].w = w;
ed[tot].next = head[u];
head[u] = tot++;
ed[tot].u = v;
ed[tot].v = u;
ed[tot].w = 0;
ed[tot].next = head[v];
head[v] = tot++;
}
bool bfs() {
memset(d, 0, sizeof(d));
d[s] = 1;
while(!q.empty()) q.pop();
q.push(s);
int x;
while(!q.empty()) {
x = q.front();
q.pop();
for(int i = head[x]; ~i; i = ed[i].next) {
if(ed[i].w && !d[ed[i].v]) {
d[ed[i].v] = d[x] + 1;
q.push(ed[i].v);
if(ed[i].v == t) return 1;
}
}
}
return 0;
}
int dinic(int x, int flow) {
if(x == t) return flow;
int res = flow, k, v;
for(int i = head[x]; ~i && res; i = ed[i].next) {
v = ed[i].v;
if(ed[i].w && d[v] == d[x] + 1) {
k = dinic(v, min(res, ed[i].w));
if(!k) d[v] = 0;
ed[i].w -= k;
ed[i^1].w += k;
res -= k;
}
}
return flow - res;
}
int work() {
int flow = 0;
while(bfs()) {
while(flow = dinic(s, inf)) maxflow += flow;
}
return maxflow;
}
}f; void tarjan(int u) {
dfn[u] = low[u] = ++num;
vis[u] = 1, stc[++top] = u;
int v;
for(int i = f.head[u]; ~i; i = f.ed[i].next) {
if(f.ed[i].w == 0) continue;
v = f.ed[i].v;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if(vis[v]) {
low[u] = min(low[u], low[v]);
}
}
if(dfn[u] == low[u]) {
cnt++;
do {
v = stc[top--];
vis[v] = 0;
c[v] = cnt;
}while(u != v);
}
} int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d%d%d%d", &n, &m, &f.s, &f.t);
f.init();
for(int i = 1; i <= m; ++i) {
scanf("%d%d%d", &u, &v, &w);
f.add(u, v, w);
}
f.work();
for(int i = 1; i <= n; ++i) {
if(!dfn[i]) tarjan(i);
}
for(int i = 0; i < f.tot; i += 2) {
if(f.ed[i].w) {
printf("0 0\n");
continue;
}
int u = f.ed[i].u, v = f.ed[i].v;
if(c[u] != c[v]) printf("1 ");
else printf("0 ");
if(c[u] == c[f.s] && c[v] == c[f.t]) printf("1\n");
else printf("0\n");
}
return 0;
}

Mincut 最小割 (BZOJ1797+最小割+tarjan)的更多相关文章

  1. BZOJ_1797_[Ahoi2009]Mincut 最小割_最小割+tarjan

    BZOJ_1797_[Ahoi2009]Mincut 最小割_最小割+tarjan Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤ ...

  2. BZOJ1797 [Ahoi2009]Mincut 最小割 【最小割唯一性判定】

    题目 A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路 ...

  3. POJ3308 Paratroopers(最小割/二分图最小点权覆盖)

    把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运 ...

  4. [学习笔记]最小割之最小点权覆盖&&最大点权独立集

    最小点权覆盖 给出一个二分图,每个点有一个非负点权 要求选出一些点构成一个覆盖,问点权最小是多少 建模: S到左部点,容量为点权 右部点到T,容量为点权 左部点到右部点的边,容量inf 求最小割即可. ...

  5. ZOJ 3792 Romantic Value 最小割(最小费用下最小边数)

    求最小割及最小花费 把边权c = c*10000+1 然后跑一个最小割,则flow / 10000就是费用 flow%10000就是边数. 且是边数最少的情况.. #include<stdio. ...

  6. bzoj2229: [Zjoi2011]最小割(分治最小割+最小割树思想)

    2229: [Zjoi2011]最小割 题目:传送门 题解: 一道非常好的题目啊!!! 蒟蒻的想法:暴力枚举点对跑最小割记录...绝对爆炸啊.... 开始怀疑是不是题目骗人...难道根本不用网络流?? ...

  7. 树形DP求树的最小支配集,最小点覆盖,最大独立集

    一:最小支配集 考虑最小支配集,每个点有两种状态,即属于支配集合或者不属于支配集合,其中不属于支配集合时此点还需要被覆盖,被覆盖也有两种状态,即被子节点覆盖或者被父节点覆盖.总结起来就是三种状态,现对 ...

  8. 求树的最大独立集,最小点覆盖,最小支配集 贪心and树形dp

    目录 求树的最大独立集,最小点覆盖,最小支配集 三个定义 贪心解法 树形DP解法 (有任何问题欢迎留言或私聊&&欢迎交流讨论哦 求树的最大独立集,最小点覆盖,最小支配集 三个定义 最大 ...

  9. 详解数组分段和最大值最小问题(最小m段和问题)

    数组分段和最大值最小问题(最小m段和问题) 问题描述 给定n个整数组成的序列,现在要求将序列分割为m段,每段子序列中的数在原序列中连续排列.如何分割才能使这m段子序列的和的最大值达到最小? 清洁工:假 ...

随机推荐

  1. Java基础之十六 数组

    数组:可以创建并组装它们,通过使用整型索引值访问它们的元素,并且它们的尺寸不能改变. 16.1 数组为什么特殊 数组与其他种类的容器之间的区别有三方面:效率,类型和保存基本类型的能力. 数组是一种效率 ...

  2. 解决github打不开

    今天重庆电信的“临时工”把github废了. 主要是github.githubassets.com和customer-stories-feed.github.com访问不到 通过修改host的方式上g ...

  3. 【操作系统之十二】分支预测、CPU亲和性(affinity)

    一.分支预测 当包含流水线技术的处理器处理分支指令时就会遇到一个问题,根据判定条件的真/假的不同,有可能会产生转跳,而这会打断流水线中指令的处理,因为处理器无法确定该指令的下一条指令,直到分支执行完毕 ...

  4. Jenkins+Docker+Git+Registry

    从0到1体验Jenkins+Docker+Git+Registry实现CI自动化发布   笔者:@拿着保温瓶的年轻人 目录: 一.前言 二.发布流程 三.环境准备 四.部署思路梳理 五.三台机器上操作 ...

  5. WeakhashMap源码2

    public class WeakHashMapIteratorTest { @SuppressWarnings({ "rawtypes", "unchecked&quo ...

  6. jquery的Layer弹出框操作

    在layer中,我们要先获取窗口的索引,然后再进行操作. var index = parent.layer.getFrameIndex(window.name); //获取窗口索引 $("# ...

  7. C语言字节对齐分析

    1.前言 什么是字节对齐呢?现代计算机中的内存空间都是按字节(byte)划分的,从理论上讲似乎任何类型的变量的访问都可以从任何地址开始,但是实际情况是在访问特定变量的时候经常需要在特定的内存地址进行访 ...

  8. Windows设置国内源阿里云镜像加速与离线安装pip包的方法

    Windows设置国内源阿里云镜像加速1.先在 windows “文件资源管理器” 地址栏 输入 %APPDATA% 按回车,打开程序自定义设置文件夹然后,创建名为 pip 的文件夹,用于存放 pip ...

  9. TeamViewer14试用版到期-怎么解决

    Teamviewer14提示试用期已到期怎么办? 问题分析: 出现这种问题,是因为在安装是选择了[公司/商务用途]或者[以上都是]这两个选项中的一个 解决方法: 1.退出TeamViewer远程软件, ...

  10. List/Map 导出到表格(使用注解和反射)

    Java 的 POI 库可以用来创建和操作 Excel 表格,有时候我们只需要简单地将 List 或 Map 导出到表格,样板代码比较多,不够优雅.如果能像 Gson 那样,使用注解标记要导出的属性, ...