博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【bzoj1797】[Ahoi2009]Mincut 最小割 网络流最小割+Tarjan
阅读量:4577 次
发布时间:2019-06-08

本文共 2700 字,大约阅读时间需要 9 分钟。

题目描述

给定一张图,对于每一条边询问:(1)是否存在割断该边的s-t最小割 (2)是否所有s-t最小割都割断该边

输入

第一行有4个正整数,依次为N,M,s和t。第2行到第(M+1)行每行3个正 整数v,u,c表示v中转站到u中转站之间有单向道路相连,单向道路的起点是v, 终点是u,切断它的代价是c(1≤c≤100000)。 注意:两个中转站之间可能有多条道路直接相连。 同一行相邻两数之间可能有一个或多个空格。

输出

对每条单向边,按输入顺序,依次输出一行,包含两个非0即1的整数,分 别表示对问题一和问题二的回答(其中输出1表示是,输出0表示否)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

样例输入

6 7 1 6

1 2 3
1 3 2
2 4 4
2 5 1
3 5 5
4 6 2
5 6 3

样例输出

1 0

1 0
0 0
1 0
0 0
1 0
1 0


题解

网络流最小割+Tarjan

(貌似是某结论题?)

跑网络流最小割,然后在残量网络上跑Tarjan,缩点。

对于一条边满流的边x->y:

如果x与y所属的SCC不同,则该边可能出现在最小割上;

如果x与s所属的SCC相同且y与t所属的SCC相同,则该边一定出现在最小割上。

具体证明可以参考  (既然是结论题就懒得证结论了233)

#include 
#include
#include
#define N 4010#define M 120010using namespace std;queue
q;typedef long long ll;int head[N] , to[M] , id[M] , next[M] , cnt = 1 , s , t , dis[N] , deep[N] , low[N] , tot , vis[N] , ins[N] , sta[N] , top , bl[N] , num , ans[M >> 1];ll val[M];inline void add(int x , int y , ll z , int i){ to[++cnt] = y , val[cnt] = z , id[cnt] = i , next[cnt] = head[x] , head[x] = cnt; to[++cnt] = x , val[cnt] = 0 , id[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt;}bool bfs(){ int x , i; memset(dis , 0 , sizeof(dis)); while(!q.empty()) q.pop(); dis[s] = 1 , q.push(s); while(!q.empty()) { x = q.front() , q.pop(); for(i = head[x] ; i ; i = next[i]) { if(val[i] && !dis[to[i]]) { dis[to[i]] = dis[x] + 1; if(to[i] == t) return 1; q.push(to[i]); } } } return 0;}ll dinic(int x , ll low){ if(x == t) return low; ll temp = low , k; int i; for(i = head[x] ; i ; i = next[i]) { if(val[i] && dis[to[i]] == dis[x] + 1) { k = dinic(to[i] , min(temp , val[i])); if(!k) dis[to[i]] = 0; val[i] -= k , val[i ^ 1] += k; if(!(temp -= k)) break; } } return low - temp;}void tarjan(int x){ int i; deep[x] = low[x] = ++tot , vis[x] = ins[x] = 1 , sta[++top] = x; for(i = head[x] ; i ; i = next[i]) { if(val[i]) { if(!vis[to[i]]) tarjan(to[i]) , low[x] = min(low[x] , low[to[i]]); else if(ins[to[i]]) low[x] = min(low[x] , deep[to[i]]); } } if(deep[x] == low[x]) { int t; num ++ ; do { t = sta[top -- ]; bl[t] = num , ins[t] = 0; }while(t != x); }}int main(){ int n , m , i , x , y; ll z; scanf("%d%d%d%d" , &n , &m , &s , &t); for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%lld" , &x , &y , &z) , add(x , y , z , i); while(bfs()) dinic(s , 1ll << 62); for(i = 1 ; i <= n ; i ++ ) if(!vis[i]) tarjan(i); for(x = 1 ; x <= n ; x ++ ) for(i = head[x] ; i ; i = next[i]) if(id[i] && !val[i]) ans[id[i]] = (bl[x] != bl[to[i]]) + ((bl[x] == bl[s] && bl[to[i]] == bl[t]) << 1); for(i = 1 ; i <= m ; i ++ ) printf("%d %d\n" , ans[i] & 1 , ans[i] >> 1); return 0;}

 

 

转载于:https://www.cnblogs.com/GXZlegend/p/7722374.html

你可能感兴趣的文章
分类---Logistic Regression
查看>>
35.Docker安装Mysql挂载Host Volume
查看>>
Ubuntu 英文下Fcitx 无法输入中文
查看>>
Android压力测试命令monkey详解
查看>>
MySQL_入手<二>之删--改--查
查看>>
MySQL创表--分页--自关联--
查看>>
python基础_面向对象进阶
查看>>
GitHub从小白到熟悉<一>
查看>>
测试基础_<一>
查看>>
定义页面加载和导航时要执行的函数/自定义事件
查看>>
rem.js
查看>>
Unslider.js Tiny Sample
查看>>
面向对象内存分析
查看>>
Dijkstra BZOJ2763 [JLOI2011]飞行路线
查看>>
前端快捷键
查看>>
重新认识成功、失败、错误、平凡、笨拙
查看>>
【模板】Hash
查看>>
洛谷 1485 火枪打怪
查看>>
Fortran编译器
查看>>
初识go
查看>>