bzoj千题计划322:bzoj2561: 最小生成树(最小割)

Posted 日拱一卒 功不唐捐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj千题计划322:bzoj2561: 最小生成树(最小割)相关的知识,希望对你有一定的参考价值。

https://www.lydsy.com/JudgeOnline/problem.php?id=2561

 

考虑Kruscal算法求最小生成树的流程

如果 u和v之间的长为L的边能出现在最小生成树里,说明<L的边不能时u和v联通

即求图中只存在<L的边时,u和v的最小割

如果 u和v之间的长为L的边能出现在最大生成树里,说明>L的边不能时u和v联通

即求图中只存在>L的边时,u和v的最小割

 

#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
 
using namespace std;
 
#define N 20001
#define M 200001
 
int n,m;
 
int tot;
int src,decc;
int front[N],to[M<<1],nxt[M<<1],cap[M<<1];
 
int lev[N],cur[N];
queue<int>q;
 
struct node
{
    int u,v,l;
}e[M];
 
void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-0; c=getchar(); }
}
 
bool bfs()
{
        for(int i=0;i<=n;++i) cur[i]=front[i],lev[i]=-1;
        while(!q.empty()) q.pop();
        q.push(src);
        lev[src]=0;
        int now,t;
        while(!q.empty())
        {
            now=q.front();
            q.pop();
            for(int i=front[now];i;i=nxt[i])
            {
                t=to[i];
                if(lev[t]==-1 && cap[i])
                {
                    lev[t]=lev[now]+1;
                    if(t==decc) return true;
                    q.push(t);
                }
            }
        }
        return false;
}
 
int dinic(int now,int flow)
{
        if(now==decc) return flow;
        int rest=0,delta;
        for(int &i=cur[now];i;i=nxt[i])
        if(cap[i] && lev[to[i]]==lev[now]+1)
        {
            delta=dinic(to[i],min(flow-rest,cap[i]));
            if(delta)
            {
                rest+=delta; 
                cap[i]-=delta; cap[i^1]+=delta;
                if(rest==flow) break;
            }
        }
        if(rest!=flow) lev[now]=-1;
        return rest;
}
 
bool cmp1(node p,node q)
{
    return p.l<q.l;
}
 
bool cmp2(node p,node q)
{
    return p.l>q.l;
}
 
void add(int u,int v,int w)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=w;
}
 
int main()
{
    read(n); read(m);
    for(int i=1;i<=m;++i) read(e[i].u),read(e[i].v),read(e[i].l);    
    read(src); read(decc);
    int L;
    read(L);
    int ans=0;
    tot=1;
    sort(e+1,e+m+1,cmp1);
    for(int i=1;i<=m;++i)
        if(e[i].l>=L) break;
        else add(e[i].u,e[i].v,1);
    while(bfs()) ans+=dinic(src,2e9);
    memset(front,0,sizeof(front));
    tot=1;
    sort(e+1,e+m+1,cmp2);
    for(int i=1;i<=m;++i)
        if(e[i].l<=L) break;
        else add(e[i].u,e[i].v,1);
    while(bfs()) ans+=dinic(src,2e9);
    printf("%d",ans);
}

 

以上是关于bzoj千题计划322:bzoj2561: 最小生成树(最小割)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2150. 部落战争(最小路径覆盖问题)BZOJ千题计划

BZOJ 2150. 部落战争(最小路径覆盖问题)BZOJ千题计划

bzoj千题计划141:bzoj3532: [Sdoi2014]Lis

bzoj千题计划227:bzo1486: [HNOI2009]最小圈j

bzoj千题计划204:bzoj1968: [Ahoi2005]COMMON 约数研究(线性筛约数个数)

bzoj千题计划113:bzoj1023: [SHOI2008]cactus仙人掌图