【BZOJ】2502清理雪道-有上下界最小流

本文深入探讨了最大流算法在网络流问题中的应用,并通过具体的代码实现展示了如何构造网络流模型,解决匹配与流量优化等问题。文章首先定义了问题背景,接着详细介绍了最大流算法的实现细节,包括数据结构的设计、核心算法的实现等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

打板可A(虽然本蒟蒻板都不会打

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cctype>
#include<queue> 
#define inf 0x7fffffff
using namespace std;
const int N=2e5+10;
int a[102][102],d[255],tot=1,S,T,SS,TT,flow,mxflow;
int n,head[255],cur[255],to[N],nxt[N],w[N],in[255];
queue<int>Q;
inline int rd()
{
    char ch=getchar();int x=0,f=1;
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
    return x*f;
} 

inline void lk(int u,int v,int val)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=val;}
inline int imin(int x,int y){return x>y?y:x;}

inline void build()
{
    int i,j;
    S=n+1;T=S+1;SS=S+2;TT=S+3;
    for(i=1;i<=n;++i) for(j=1;j<=a[i][0];++j) {
       lk(i,a[i][j],inf),lk(a[i][j],i,0);
       in[i]--;in[a[i][j]]++;
    }
    for(i=1;i<=n;++i){
        lk(S,i,inf);lk(i,S,0);lk(i,T,inf);lk(T,i,0);
        if(in[i]>0) lk(SS,i,in[i]),lk(i,SS,0);
        else lk(i,TT,-in[i]),lk(TT,i,0); 
    }
}

inline bool bfs(int s,int t)
{
    int i,j;
    for(i=1;i<=TT;++i) d[i]=-1;
    d[s]=0;Q.push(s);int x;
    while(!Q.empty()){
        x=Q.front();Q.pop();
        for(i=head[x];i;i=nxt[i]){
            j=to[i];
            if(d[j]==-1 && w[i]){
                d[j]=d[x]+1;
                Q.push(j);
            }   
        }
    } 
    return d[t]!=-1;  
}

inline int dfs(int s,int t,int f)
{
    if(s==t) return f;
    int ss=0,ret;
    for(int j,i=cur[s];i;i=nxt[i]){
        j=to[i];
        if(d[j]==d[s]+1 && w[i]){
            ret=f-ss;ret=dfs(j,t,imin(ret,w[i]));
            if(!ret){cur[s]=i;continue;}
            w[i]-=ret;w[i^1]+=ret;ss+=ret;
            if(ss==f) return f;
        }
    }
    if(!ss) d[s]=-1;
    return ss;
}

inline int dinic(int s,int t)
{
    int ret=0,i;
    while(bfs(s,t)){
        for(i=1;i<=TT;++i) cur[i]=head[i];
        ret+=dfs(s,t,inf);
    }
    return ret;
}

int main(){
    int i,j;
    n=rd();
    for(i=1;i<=n;++i){
        a[i][0]=rd();
        for(j=1;j<=a[i][0];++j)a[i][j]=rd();
    }
    build();
    lk(T,S,inf);lk(S,T,0);
    dinic(SS,TT); 
    mxflow=w[tot];
    head[S]=nxt[head[S]];head[T]=nxt[head[T]];
    for(i=head[SS];i;i=nxt[i]) w[i]=0,w[i^1]=0;
    for(i=head[TT];i;i=nxt[i]) w[i]=0,w[i^1]=0;
    lk(SS,T,inf);lk(T,SS,0);lk(S,TT,inf);lk(TT,S,0);
    flow=dinic(SS,TT);
    printf("%d\n",mxflow-flow);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值