正题

题目链接:https://www.luogu.com.cn/problem/P4126


题目大意

给出\(n\)个点\(m\)条边的一张有向图和起点终点。对于每条边求其是否是最小割的可行割/必须割

\(1\leq n\leq 4000,1\leq m\leq 60000\)


解题思路

一些结论吧,首先是可行割,跑一次最大流,然后如果一条边是可行割需要满足

  • 该边满流
  • 残量网络上没有\(x,y\)之间的环

首先满流是显然的,然后第二个结论的话,如果它们之间有环,那么从\(y\)顺着环的方向逆流回去的话那么最大流不变但是这条边的流量减少了。

然后必须割的话也是两个条件

  • 该边满流
  • 残量网络上\(s\)能到\(x\),\(y\)能到\(t\)

这个我直接搬之前的证明了

证明:在残量网络上\(s\)可以到达\(x\)且\(y\)可以到达\(t\)那么说明若该边不割那么\(s\)就可以通过该边到达\(t\)。假设在\(s\)到\(x\)的路上有同样长度的一条道路且割掉后可以使\(s\)到达\(x\)那么在残量网络上该边的流量必定为0,因为切割掉\(x->y\)的流量也必定会经过该边所以在残量网络上\(s\)就不可以到达\(x\)了。所以该假设不成立。

证毕

所以跑完最大流再跑一次\(tarjan\)然后按照上面判就好了


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
const int N=4100,M=6e4+10,inf=1e9;
struct node{
int to,next,w;
}a[M<<1];
int n,m,s,t,tot,cnt,num,ls[N],id[M];
int dep[N],dfn[N],low[N],col[N];
bool ins[N];
stack<int> st;queue<int> q;
void addl(int x,int y,int w){
a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;
a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;
return;
}
bool bfs(){
while(!q.empty())q.pop();q.push(s);
memset(dep,0,sizeof(dep));dep[s]=1;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(dep[y]||!a[i].w)continue;
dep[y]=dep[x]+1;
if(y==t)return 1;
q.push(y);
}
}
return 0;
}
int dinic(int x,int flow){
if(x==t)return flow;
int rest=0,k;
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(dep[x]+1!=dep[y]||!a[i].w)continue;
rest+=(k=dinic(y,min(flow-rest,a[i].w)));
a[i].w-=k;a[i^1].w+=k;
if(rest==flow)return rest;
}
if(!rest)dep[x]=0;
return rest;
}
void tarjan(int x){
dfn[x]=low[x]=++cnt;
ins[x]=1;st.push(x);
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(!a[i].w)continue;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(ins[y])
low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x]){
int k;++num;
do{
k=st.top();st.pop();
col[k]=num;ins[k]=0;
}while(k!=x);
}
return;
}
signed main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);tot=1;
for(int i=1;i<=m;i++){
int x,y,w;id[i]=tot+1;
scanf("%d%d%d",&x,&y,&w);
addl(x,y,w);
}
while(bfs())
dinic(s,inf);
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan(i);
for(int i=1;i<=m;i++){
int x=a[id[i]^1].to,y=a[id[i]].to;
if(a[id[i]].w==0&&col[x]!=col[y])putchar('1');else putchar('0');putchar(' ');
if(a[id[i]].w==0&&col[x]==col[s]&&col[y]==col[t])putchar('1');else putchar('0');putchar('\n');
}
return 0;
}

P4126-[AHOI2009]最小割【网络流,tarjan】的更多相关文章

  1. P4126 [AHOI2009]最小割(网络流+tarjan)

    P4126 [AHOI2009]最小割 边$(x,y)$是可行流的条件: 1.满流:2.残量网络中$x,y$不连通 边$(x,y)$是必须流的条件: 1.满流:2.残量网络中$x,S$与$y,T$分别 ...

  2. P4126 [AHOI2009]最小割

    题目地址:P4126 [AHOI2009]最小割 最小割的可行边与必须边 首先求最大流,那么最小割的可行边与必须边都必须是满流. 可行边:在残量网络中不存在 \(x\) 到 \(y\) 的路径(强连通 ...

  3. 洛谷P4126 [AHOI2009]最小割

    题目:洛谷P4126 [AHOI2009]最小割 思路: 结论题 在残余网络上跑tarjan求出所有SCC,记id[u]为点u所在SCC的编号.显然有id[s]!=id[t](否则s到t有通路,能继续 ...

  4. 洛谷$P4126\ [AHOI2009]$最小割 图论

    正解:网络流+$tarjan$ 解题报告: 传送门$QwQ$ $umm$最小割的判定问题$QwQ$,因为并不会做是看的题解才会的,所以也没什么推导过程直接放结论趴$QwQ$ 首先跑个最大流,然后有. ...

  5. 【BZOJ1797】[AHOI2009]最小割(网络流)

    [BZOJ1797][AHOI2009]最小割(网络流) 题面 BZOJ 洛谷 题解 最小割的判定问题,这里就当做记结论吧.(源自\(lun\)的课件) 我们先跑一遍最小割,求出残量网络.然后把所有还 ...

  6. 【bzoj1797】[Ahoi2009]Mincut 最小割 网络流最小割+Tarjan

    题目描述 给定一张图,对于每一条边询问:(1)是否存在割断该边的s-t最小割 (2)是否所有s-t最小割都割断该边 输入 第一行有4个正整数,依次为N,M,s和t.第2行到第(M+1)行每行3个正 整 ...

  7. BZOJ 1797: [Ahoi2009]Mincut 最小割( 网络流 )

    先跑网络流, 然后在残余网络tarjan缩点. 考虑一条边(u,v): 当且仅当scc[u] != scc[v], (u,v)可能出现在最小割中...然而我并不会证明 当且仅当scc[u] = scc ...

  8. bzoj 1797: [Ahoi2009]Mincut 最小割【tarjan+最小割】

    先跑一遍最大流,然后对残量网络(即所有没有满流的边)进行tarjan缩点. 能成为最小割的边一定满流:因为最小割不可能割一半的边: 连接s.t所在联通块的满流边一定在最小割里:如果不割掉这条边的话,就 ...

  9. AHOI2009最小割

    1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1072  Solved: 446[Submit] ...

  10. BZOJ1797:[AHOI2009]最小割(最小割)

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

随机推荐

  1. Socket入门Demo

    一.简单介绍下Socket编程    申明:.net网络编程 1)什么是Socket编程? Socket编程就是常说的网络通讯编程,套接字编程.一般应用于软件聊天通讯,以及软件与硬件之间的通讯. 通熟 ...

  2. qt 中回调函数的实现

    在QT中回调函数主要可以实现多态性,通过回调函数可以动态处理一些操作.在多线程中,当同时需要处理多个事务的时候,显然你会去创建多个线程类然后实例化,这显然会增加开发工作,当我们在线程类中加入一个回调函 ...

  3. linux中 ~ 表示的是什么目录?

    ~ 表示代码主目录,也就是当前登录用户的用户目录.比如:我登录用户是chencd ~~ 代表的就是 /home/chen/当然前提是有用户目录,如果没有/home/chen目录的话情况就比较多了.总之 ...

  4. Object 的wait()方法

    The java.lang.Object.wait() causes current thread to wait until another thread invokes the notify() ...

  5. n个容器取油问题再探

    在 韩信分油问题的拓展分析 里,最后给出了一般性的结论,即: 用 n (n > 1) 个不规则无刻度的容器从一个无穷大的油桶里取油,这些容器容量都为整数升,分别记为 a1, a2, ..., a ...

  6. 一次PHP大马提权

    记一次PHP提权 发现 PHP大马:指木马病毒:PHP大马,就是PHP写的提取站点权限的程序:因为带有提权或者修改站点功能,所以称为叫木马. 自从师哥那里听说过之后,一直感叹于PHP大马的神奇...但 ...

  7. vue element-ui 做分页功能之封装

    在 vue 项目中的 components 中 创建一个 文件夹,文件夹里创建一个 name(这个名字你随意取).vue <template>   <div class=" ...

  8. 办公室文员必备python神器,将PDF文件表格转换成excel表格!

    [阅读全文] 第三方库说明 # PDF读取第三方库 import pdfplumber # DataFrame 数据结果处理 import pandas as pd 初始化DataFrame数据对象 ...

  9. jvm学习笔记:程序计数器

    程序计数器(PC Register) The Java Virtual Machine can support many threads of execution at once (JLS §17). ...

  10. 自定义-starter

    目录 说明 编写启动器 新建项目测试我们自己写的启动器 分析完毕了源码以及自动装配的过程,可以尝试自定义一个启动器来玩玩! 自动装配的过程 SpringBoot-静态资源加载-源码 SpringBoo ...