[BZOJ1797][AHOI2009]最小割Mincut

bzoj
luogu

sol

一条边出现在最小割集中的必要条件和充分条件。
先跑出任意一个最小割,然后在残余网络上跑出\(scc\)。
一条边\((u,v)\)在最小割集中的必要条件:\(bel[u]!=bel[v]\)
一条边\((u,v)\)在最小割集中的充分条件:\(bel[u]=bel[S],bel[v]=bel[T]\)

code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='0') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
const int N = 4005;
const int inf = 1e9;
struct edge{int to,nxt,w;}a[N*30];
int n,m,s,t,head[N],cnt=1,dep[N],cur[N],dfn[N],low[N],vis[N],Stack[N],top,bel[N],scc;
queue<int>Q;
void link(int u,int v,int w)
{
    a[++cnt]=(edge){v,head[u],w};
    head[u]=cnt;
    a[++cnt]=(edge){u,head[v],0};
    head[v]=cnt;
}
bool bfs()
{
    memset(dep,0,sizeof(dep));
    dep[s]=1;Q.push(s);
    while (!Q.empty())
    {
        int u=Q.front();Q.pop();
        for (int e=head[u];e;e=a[e].nxt)
            if (a[e].w&&!dep[a[e].to])
                dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
    }
    return dep[t];
}
int dfs(int u,int f)
{
    if (u==t) return f;
    for (int &e=cur[u];e;e=a[e].nxt)
        if (a[e].w&&dep[a[e].to]==dep[u]+1)
        {
            int tmp=dfs(a[e].to,min(a[e].w,f));
            if (tmp) {a[e].w-=tmp;a[e^1].w+=tmp;return tmp;}
        }
    return 0;
}
void Dinic()
{
    while (bfs())
    {
        for (int i=1;i<=n;++i) cur[i]=head[i];
        while (dfs(s,inf)) ;
    }
}
void Tarjan(int u)
{
    dfn[u]=low[u]=++cnt;
    Stack[++top]=u;vis[u]=1;
    int v;
    for (int e=head[u];e;e=a[e].nxt)
        if (a[e].w)
        {
            v=a[e].to;
            if (!dfn[v]) Tarjan(v),low[u]=min(low[u],low[v]);
            else if (vis[v]) low[u]=min(low[u],dfn[v]);
        }
    if (dfn[u]==low[u])
    {
        ++scc;
        do{
            v=Stack[top--];
            vis[v]=0;bel[v]=scc;
        }while (u!=v);
    }
}
int main()
{
    n=gi();m=gi();s=gi();t=gi();
    for (int i=1;i<=m;++i)
    {
        int u=gi(),v=gi(),w=gi();
        link(u,v,w);
    }
    Dinic();cnt=0;
    for (int i=1;i<=n;++i) if (!dfn[i]) Tarjan(i);
    for (int i=1;i<=m;++i)
    {
        int u=a[i<<1|1].to,v=a[i<<1].to;
        printf("%d ",bel[u]!=bel[v]&&!a[i<<1].w);
        printf("%d\n",bel[u]==bel[s]&&bel[v]==bel[t]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zhoushuyu/p/8707683.html

时间: 2024-07-31 10:01:52

[BZOJ1797][AHOI2009]最小割Mincut的相关文章

AHOI2009最小割

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1072  Solved: 446[Submit][Status] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案,使中转站s不能到

AHOI2009 最小割

题目链接:戳我 题目就是两问,一问是求所有最小割方案中出现至少一次的边(可能割边),一问是求所有最小割方案中一定会出现的边. 其实对于这个问题,我们有结论-- 1.跑一遍网络流之后,对残量网络做SCC,满流且边的两个端点不在同一个SCC中的边是可能割边. 2.跑一遍网络流之后,对残量网络做SCC,满流,边的两个端点分别和S和T在同一个SCC里,这个边就是一定会在最小割中出现. 考虑证明......其实我并不能严谨证明,这里就抄一下网上的解释好了 证明1:考虑如果减少一条边的容量之后,最小割变小了

[BZOJ 1797][AHOI2009]最小割(最小割关键边的判断)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1797 分析: 在残余网络中看: 对于第1问: 1.首先这个边必须是满流 2.其次这个边连接的两个点U,V必须属于两个SCC,即这个边必须为一个割 对于第2问: 在第1问的基础上,还要判断U和S.V和T是否分别在同一个SCC中,如果成立,那么这样才是必须的.

P4126 [AHOI2009]最小割

传送门 需要对网络流有较深的理解... 跑完最大流后判断一条边是否可以成为割边的充分必要条件是: $1.$ 满流 $2.$ 此边连接的两点 $(u,v)$ 在残量网络上不存在从 $u$ 到 $v$ 的路径 感性理解一下就是如果不满足说明它不能成为 "瓶颈" 跑完最大流后判断一条边是否必须为割边的充分必要条件是: $1.$ 满流 $2.$ 此边连接的两点 $(u,v)$ ,在残量网络上从源点有一条路径到 $u$ ,从 $v$ 有一条路径到 $T$ 感性理解一下就是如果满足说明它一定是 &

最小割-poj-2914

poj-2914-Minimum Cut Description Given an undirected graph, in which two vertices can be connected by multiple edges, what is the size of the minimum cut of the graph? i.e. how many edges must be removed at least to disconnect the graph into two subg

PCL—点云分割(最小割算法)

1.点云分割的精度 在之前的两个章节里介绍了基于采样一致的点云分割和基于临近搜索的点云分割算法.基于采样一致的点云分割算法显然是意识流的,它只能割出大概的点云(可能是杯子的一部分,但杯把儿肯定没分割出来).基于欧式算法的点云分割面对有牵连的点云就无力了(比如风筝和人,在不用三维形态学去掉中间的线之前,是无法分割风筝和人的).基于法线等信息的区域生长算法则对平面更有效,没法靠它来分割桌上的碗和杯子.也就是说,上述算法更关注能不能分割,除此之外,我们还需要一个方法来解决分割的"好不好"这个

[bzoj1797] [Ahoi2009]Mincut 最小割

问最小割中可能成为割边和一定会成为割边的边有哪些. 膜了半天各路题解. 比较详细的解释: http://blog.csdn.net/horizon_smz/article/details/50889806 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=4023,m

【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1685  Solved: 724[Submit][Status][Discuss] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案

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

先跑网络流, 然后在残余网络tarjan缩点. 考虑一条边(u,v): 当且仅当scc[u] != scc[v], (u,v)可能出现在最小割中...然而我并不会证明 当且仅当scc[u] = scc[S] && scc[v] == scc[T], (u, v) 必定出现在最小割中. 这个很好脑补, 假如这条边不是满流, 那么S-T就存在增广路了.. ----------------------------------------------------------------------