网络流模板

此处过滤最水的匈牙利算法。

最大流&最小割https://www.lydsy.com/JudgeOnline/problem.php?id=2127

#include<cstdio>
#include<algorithm>
#include<cstring>
#define FOR(x,y) for(int i=1;i<=x;i++)for(int j=1;j<=y;j++)
const int N=50100,M=3e5+7;
using namespace std;
int n,m,T,cnt,tot,ans,hd[N],lv[N],q[N],v[M],nxt[M],w[M];
void adde(int x,int y,int z)
{
    v[++cnt]=y,w[cnt]=z,nxt[cnt]=hd[x],hd[x]=cnt;
    v[++cnt]=x,w[cnt]=0,nxt[cnt]=hd[y],hd[y]=cnt;
}
bool bfs()
{
    int qs=0,qe=1;
    memset(q,0,sizeof q);
    memset(lv,0,sizeof lv);
    q[0]=0,lv[0]=1;
    while(qs<qe)
    {
        int u=q[qs++];
        if(u==T)break;
        for(int i=hd[u];i;i=nxt[i])
        if(w[i]&&!lv[v[i]]){lv[v[i]]=lv[u]+1;q[qe++]=v[i];}
    }
    if(lv[T])return 1;return 0;
}
int dfs(int u,int low)
{
    if(u==T||!low)return low;
    int sum=0;
    for(int i=hd[u];i;i=nxt[i])
    if(w[i]&&lv[v[i]]==lv[u]+1)
    {
        int tmp=dfs(v[i],min(w[i],low));
        sum+=tmp,low-=tmp,w[i]-=tmp,w[i^1]+=tmp;
        if(!low)return sum;
    }
    if(low)lv[u]=-1;
    return sum;
}
int id(int x,int y){return(x-1)*m+y;}
int main()
{
    scanf("%d%d",&n,&m);
    T=5*n*m+1,cnt=1,tot=n*m;
    int x;
    FOR(n,m)scanf("%d",&x),adde(0,id(i,j),x),ans+=x;
    FOR(n,m)scanf("%d",&x),adde(id(i,j),T,x),ans+=x;
    FOR(n-1,m)
    scanf("%d",&x),tot++,adde(0,tot,x),adde(tot,id(i,j),1e9),adde(tot,id(i+1,j),1e9),ans+=x;
    FOR(n-1,m)
    scanf("%d",&x),tot++,adde(tot,T,x),adde(id(i,j),tot,1e9),adde(id(i+1,j),tot,1e9),ans+=x;
    FOR(n,m-1)
    scanf("%d",&x),tot++,adde(0,tot,x),adde(tot,id(i,j),1e9),adde(tot,id(i,j+1),1e9),ans+=x;
    FOR(n,m-1)
    scanf("%d",&x),tot++,adde(tot,T,x),adde(id(i,j),tot,1e9),adde(id(i,j+1),tot,1e9),ans+=x;
    while(bfs())ans-=dfs(0,1e9);
    printf("%d",ans);
}

费用流https://www.luogu.org/problemnew/show/P3705

#include<bits/stdc++.h>
using namespace std;
const int N=207;
struct edge{int u,v,w,nxt;double c;}e[N*N*4];
queue<int>q;
int n,S,T,ecnt,hd[N],vis[N],pre[N];
double a[N][N],b[N][N],d[N];
void adde(int x,int y,int z,double c)
{
    e[++ecnt]=(edge){x,y,z,hd[x],c},hd[x]=ecnt;
    e[++ecnt]=(edge){y,x,0,hd[y],-c},hd[y]=ecnt;
}
bool spfa()
{
    for(int i=S;i<=T;i++)d[i]=-1e18,pre[i]=0;
    d[S]=0,q.push(S);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        vis[u]=0;
        for(int i=hd[u];i;i=e[i].nxt)
        if(e[i].w&&d[u]+e[i].c>d[e[i].v])
        {
            pre[e[i].v]=i,d[e[i].v]=d[u]+e[i].c;
            if(!vis[e[i].v])q.push(e[i].v),vis[e[i].v]=1;
        }
    }
    return d[T]>-1e18;
}
bool check()
{
    double ret=0;
    while(spfa())
    {
        int mn=1e9+7;
        for(int i=pre[T];i;i=pre[e[i^1].v])mn=min(mn,e[i].w);
        for(int i=pre[T];i;i=pre[e[i^1].v])e[i].w-=mn,e[i^1].w+=mn;
        ret+=mn*d[T];
    }
    return ret>0;
}
int main()
{
    scanf("%d",&n),T=2*n+1;
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%lf",&a[i][j]);
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%lf",&b[i][j]);
    double l=0,r=10086,mid;
    while(r-l>1e-7)
    {
        mid=(l+r)/2;
        ecnt=1;
        memset(hd,0,sizeof hd);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        adde(i,j+n,1,a[i][j]-mid*b[i][j]);
        for(int i=1;i<=n;i++)adde(S,i,1,0),adde(i+n,T,1,0);
        if(check())l=mid;else r=mid;
    }
    printf("%.6lf",l);
}

KMhttps://www.luogu.org/problemnew/show/P4412

#include<bits/stdc++.h>
using namespace std;
const int N=1100,M=21000;
struct edge{int u,v,nxt,w,id;}a[M],e[M];
bool is[M];
int n,m,cnt,hd[N],fa[N],deep[N],pre[M],f[N][N],mat[N],lx[N],rx[N],need[N],mp[N][N];
bool vl[N],vr[N];
void add(int x,int y,int z,int id)
{e[++cnt]=(edge){x,y,hd[x],z,id};hd[x]=cnt;}
void dfs(int u)
{
    for(int i=hd[u];i;i=e[i].nxt)
    if(e[i].v!=fa[u])
    {
        fa[e[i].v]=u;
        deep[e[i].v]=deep[u]+1;
        pre[e[i].v]=i;
        dfs(e[i].v);
    }
}
void build(int u,int i)
{
    int x=a[i].u,y=a[i].v;
    while(x!=y)
    {
        if(deep[x]>deep[y])swap(x,y);
        int k=pre[y];
        f[u][e[k].id]=e[k].w-a[i].w;
        y=fa[y];
    }
}
bool find(int x)
{
    vl[x]=1;
    for(int i=1;i<=n;i++)
    if(!vr[i])
    {
        if(lx[x]+rx[i]==f[x][i])
        {
            vr[i]=1;
            if(!mat[i]||find(mat[i]))
            {
                mat[i]=x;
                return 1;
            }
        }
        else need[i]=min(need[i],lx[x]+rx[i]-f[x][i]);
    }
    return 0;
}
void km()
{
    memset(mat,0,sizeof mat);
    memset(lx,0,sizeof lx);
    memset(rx,0,sizeof rx);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    lx[i]=max(lx[i],f[i][j]);
    for(int i=1;i<=n;i++)
    {
        memset(need,63,sizeof need);
        while(1)
        {
            memset(vl,0,sizeof vl);
            memset(vr,0,sizeof vr);
            if(find(i))break;
            int d=2147483647;
            for(int j=1;j<=n;j++)if(!vr[j])d=min(d,need[j]);
            for(int j=1;j<=n;j++)
            {
                if(vl[j])lx[j]-=d;
                if(vr[j])rx[j]+=d;
                else need[j]-=d;
            }
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)ans+=f[mat[i]][i];
    printf("%d",ans);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w),mp[a[i].u][a[i].v]=i;
    for(int i=1,x,y;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        is[mp[x][y]]=1;
        add(x,y,a[mp[x][y]].w,i);
        add(y,x,a[mp[x][y]].w,i);
    }
    deep[1]=1;
    dfs(1);
    for(int i=1,tp=0;i<=m;i++)
    if(!is[i])build(++tp,i);
    n=max(n-1,m-n+1);
    km();
}

有上下界的网络流https://www.lydsy.com/JudgeOnline/problem.php?id=2502

#include<bits/stdc++.h>
using namespace std;
const int N=30100,M=500100;
struct edge{int v,nxt,c;}e[M];
int n,m,cnt=1,ans,S,T,hd[N],lv[N],q[N];
void add(int u,int v,int w)
{
    e[++cnt]=(edge){v,hd[u],w};hd[u]=cnt;
    e[++cnt]=(edge){u,hd[v],0};hd[v]=cnt;
}
bool bfs()
{
    int qs=0,qe=1;
    memset(lv,0,sizeof lv);
    q[0]=0;lv[0]=1;
    while(qs<qe)
    {
        int u=q[qs++];if(u==T)break;
        for(int i=hd[u];i;i=e[i].nxt)
        if(e[i].c&&!lv[e[i].v])lv[e[i].v]=lv[u]+1,q[qe++]=e[i].v;
    }
    return lv[T];
}
int dfs(int u,int f)
{
    if(u==T)return f;
    int sum=0,tmp;
    for(int i=hd[u];i;i=e[i].nxt)
    if(e[i].c&&lv[e[i].v]==lv[u]+1)
    {
        tmp=dfs(e[i].v,min(f,e[i].c));
        sum+=tmp;f-=tmp;
        e[i].c-=tmp;e[i^1].c+=tmp;
    }
    if(!sum)lv[u]=-1;
    return sum;
}
void solve(){while(bfs())ans+=dfs(0,1e9);}
int main()
{
    scanf("%d",&n);
    int x,y;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        while(x--)
        {
            scanf("%d",&y);m++;
            add(i,n+2*m-1,1e9);add(n+2*m,y,1e9);
            add(n+2*m-1,n+2*m,1e9);
        }
    }
    S=n+2*m+1;T=S+1;
    for(int i=1;i<=n;i++)add(S,i,1e9);
    for(int i=1;i<=m;i++)add(0,n+2*i,1),add(n+2*i-1,T,1);
    for(int i=1;i;i++){add(0,S,1);solve();if(ans==m){printf("%d",i);break;}}
}

霍尔定理https://www.lydsy.com/JudgeOnline/problem.php?id=3693

#include<bits/stdc++.h>
#define lson l,mid,rt*2
#define rson mid+1,r,rt*2+1
using namespace std;
const int N=4e5+7;
struct que{int l,r,a;}q[N];
int n,m,a[N],mx[N*4],lazy[N*4];
bool operator<(que a,que b){return a.r<b.r;}
void build(int l,int r,int rt)
{
    if(l==r){mx[rt]=a[l]-1;return;}
    int mid=(l+r)/2;
    build(lson);build(rson);
    mx[rt]=max(mx[rt*2],mx[rt*2+1]);
}
void pushdown(int rt)
{
    if(!lazy[rt])return;
    lazy[rt*2]+=lazy[rt];mx[rt*2]+=lazy[rt];
    lazy[rt*2+1]+=lazy[rt];mx[rt*2+1]+=lazy[rt];
    lazy[rt]=0;
}
void add(int L,int R,int c,int l,int r,int rt)
{
    if(L<=l&&r<=R){mx[rt]+=c;lazy[rt]+=c;return;}
    int mid=(l+r)/2;
    pushdown(rt);
    if(L<=mid)add(L,R,c,lson);
    if(R>mid)add(L,R,c,rson);
    mx[rt]=max(mx[rt*2],mx[rt*2+1]);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)return mx[rt];
    pushdown(rt);
    int mid=(l+r)/2,ret=0;
    if(L<=mid)ret=max(ret,query(L,R,lson));
    if(R>mid)ret=max(ret,query(L,R,rson));
    return ret;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        int sum=0,tot=n;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].a);
            q[i].l++,q[i].r++;
            sum+=q[i].a;
            if(q[i].l>q[i].r)q[i].r+=m;
            else q[++tot].l=q[i].l+m,q[tot].r=q[i].r+m,q[tot].a=q[i].a;
        }
        if(sum>m){puts("No");continue;}
        n=tot;tot=0;
        for(int i=1;i<=n;i++)a[++tot]=q[i].l,a[++tot]=q[i].r;
        sort(a+1,a+tot+1);
        tot=unique(a+1,a+tot+1)-a-1;
        memset(lazy,0,sizeof lazy);
        memset(mx,0,sizeof mx);
        build(1,tot,1);
        sort(q+1,q+n+1);
        bool flag=1;
        for(int i=1;i<=n;i++)
        {
            q[i].l=lower_bound(a+1,a+tot+1,q[i].l)-a;
            q[i].r=lower_bound(a+1,a+tot+1,q[i].r)-a;
            add(1,q[i].l,q[i].a,1,tot,1);
            if(query(1,q[i].r,1,tot,1)>a[q[i].r]){flag=0;break;}
        }
        if(flag)puts("Yes");else puts("No");
    }
}

完结撒花

原文地址:https://www.cnblogs.com/hfctf0210/p/11039228.html