网络流刷题集

一.洛谷网络流24题(部分)

洛谷这些题都有很好的题解,这里就不再赘述了(懒)..

飞行员配对方案问题

#include<bits/stdc++.h>
using namespace std;
const int s=0,t=101;
int n,m,next[20010],head[110],to[20010],las[20010],deep[110],num=-1;
void add_edge(int u,int v,int w)
{
    next[++num]=head[u],
    to[num]=v,las[num]=w,
    head[u]=num;
}
bool bfs()
{
    memset(deep,0,sizeof deep);
    deep[s]=1;queue<int>q;
    q.push(s);int nw;
    while(!q.empty())
    {
        nw=q.front(),q.pop();
        for(int i=head[nw];i!=-1;i=next[i])
        if(las[i]&&!deep[to[i]])deep[to[i]]=deep[nw]+1,q.push(to[i]);
    }
    return deep[t];
}
int dfs(int pos,int flow)
{
    if(pos==t)return flow;
    for(int i=head[pos];i!=-1;i=next[i])
    {
        if(las[i]&&deep[to[i]]==deep[pos]+1)
        {
            int nw=dfs(to[i],min(flow,las[i]));
            if(nw)
            {
                las[i]-=nw;las[i^1]+=nw;
                return nw;
            }   
        }
    }
    return 0;
}
void dinic()
{
    int ans=0,tmp;
    while(bfs())
    {
        while(tmp=dfs(s,1e9))
            ans+=tmp;
    }
    printf("%d\n",ans);
    for(int i=1;i<=m;i++)
    for(int j=head[i];j!=-1;j=next[j])
    {
        if(!las[j]&&to[j]!=s){
            printf("%d %d\n",i,to[j]);
            break;
        }
    }
}
int main()
{
    int i=0,j=0;
    scanf("%d%d",&m,&n);
    memset(head,-1,sizeof head),
    memset(next,-1,sizeof next);
    for(int i=1;i<=m;i++)
    add_edge(s,i,1),add_edge(i,s,0);
    for(int i=m+1;i<=n;i++)
    add_edge(i,t,1),add_edge(t,i,0);
    while(~scanf("%d%d",&i,&j))
    {
        if(i==-1&&j==-1)break;
        if(i>j)swap(i,j);
        add_edge(i,j,1),add_edge(j,i,0);
    }
    dinic();
}

方格取数问题

#include<bits/stdc++.h>
using namespace std;
int hd[10010],nxt[200010],las[200010],to[200010],num=-1,cur[10010],deep[10010],sum=0;
const int s=0,t=10005;
void add_edge(int u,int v,int w)
{
    nxt[++num]=hd[u],to[num]=v,
    las[num]=w,hd[u]=num;
}
void add(int u,int v,int w)
{add_edge(u,v,w),add_edge(v,u,0);}
bool bfs()
{
    memset(deep,0,sizeof deep);
    int nw;queue<int>q;
    q.push(s);deep[s]=1;
    while(!q.empty())
    {
        nw=q.front(),q.pop();
        for(int i=hd[nw];i!=-1;i=nxt[i])
        {
            if(las[i]>0&&!deep[to[i]])
            {
                deep[to[i]]=deep[nw]+1;
                q.push(to[i]);
            }
        }
    }
    return deep[t];
}
int dfs(int pos,int flow)
{
    if(pos==t)return flow;
    int nw;
    for(int &i=cur[pos];i!=-1;i=nxt[i])
    {
        if(las[i]>0&&deep[to[i]]==deep[pos]+1)
        {
            nw=dfs(to[i],min(flow,las[i]));
            if(nw>0)
            {
                las[i]-=nw;
                las[i^1]+=nw;
                return nw;
            }
        }
    }
    return 0;
}
void dinic()
{
    int tmp,ans=0;
    while(bfs())
    {
        for(int i=s;i<=t;i++)cur[i]=hd[i];
        while(tmp=dfs(s,2e9))ans+=tmp;
    }
    printf("%d",sum-ans);
}
int main()
{
    int n,m,tmp;
    memset(nxt,-1,sizeof nxt),
    memset(hd,-1,sizeof hd);
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&tmp),sum+=tmp,(i+j)&1?add(s,(i-1)*n+j,tmp):add((i-1)*n+j,t,tmp);
            if((i+j)&1)
            {
                if(i>1)add((i-1)*n+j,(i-2)*n+j,2e9);if(i<m)add((i-1)*n+j,i*n+j,2e9);if(j>1)add((i-1)*n+j,(i-1)*n+j-1,2e9);if(j<n)add((i-1)*n+j,(i-1)*n+j+1,2e9);
            }
        }
    }
    dinic();
}

圆桌问题

#include<bits/stdc++.h>
using namespace std;
const int s=0,t=500;
int m,n,sum=0,to[100010],hd[510],nxt[100010],las[100010],num=-1,deep[510],cur[510];
void add_edge(int u,int v,int w)
{
    nxt[++num]=hd[u],las[num]=w,
    to[num]=v,hd[u]=num;
}
void add(int u,int v,int w)
{
    add_edge(u,v,w),
    add_edge(v,u,0);
}
bool bfs()
{
    memset(deep,0,sizeof deep);
    queue<int>q;int nw;
    deep[s]=1;q.push(s);
    while(!q.empty())
    {
        nw=q.front(),q.pop();
        for(int i=hd[nw];i!=-1;i=nxt[i])
        {
            if(las[i]>0&&!deep[to[i]])deep[to[i]]=deep[nw]+1,q.push(to[i]);
        }
    }
    return deep[t];
}
int dfs(int pos,int flow)
{
    if(pos==t)return flow;
    int nw;
    for(int &i=cur[pos];i!=-1;i=nxt[i])
    {
        if(las[i]>0&&deep[to[i]]==deep[pos]+1)
        {
            nw=dfs(to[i],min(flow,las[i]));
            if(nw>0)
            {
                las[i]-=nw;
                las[i^1]+=nw;
                return nw;
            }
        }
    }
    return 0;
}
void dinic()
{
    int flow=0;
    while(bfs())
    {
        for(int i=0;i<=500;i++)cur[i]=hd[i];
        while(int tmp=dfs(s,1e9))flow+=tmp;
    }
    if(flow==sum)
    {
        printf("1\n");
        for(int i=1;i<=m;i++)
        {
            for(int j=hd[i];j!=-1;j=nxt[j])
            {
                if(to[j]!=s&&las[j]==0)
                {
                    printf("%d ",to[j]-m);
                }
            }
            puts("");
        }
    }
    else printf("0\n");
}
int main()
{
    int tp;
    memset(hd,-1,sizeof hd),
    memset(nxt,-1,sizeof nxt);
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++)
    for(int j=1;j<=n;j++)
    add(i,m+j,1);
    for(int i=1;i<=m;i++)
    scanf("%d",&tp),sum+=tp,add(s,i,tp);
    for(int i=1;i<=n;i++)
    scanf("%d",&tp),add(i+m,t,tp);
    dinic();
}

骑士共存问题

#include<bits/stdc++.h>
using namespace std;
const int s=0,t=40005;
const int dx[]={2,2,1,1,-1,-1,-2,-2};
const int dy[]={1,-1,2,-2,2,-2,1,-1};
bool vis[210][210];
int m,n,hd[40010],nxt[1000010],las[1000010],to[1000010],num=-1,cur[40010],deep[40010];
inline void add_edge(int u,int v,int w)
{
    nxt[++num]=hd[u],las[num]=w,
    to[num]=v,hd[u]=num;
}
inline void add(int u,int v,int w)
{add_edge(u,v,w),add_edge(v,u,0);}
inline int get(int i,int j)
{return (i-1)*n+j;}
inline bool bfs()
{
    memset(deep,0,sizeof deep);
    queue<int>q;int nw;
    deep[s]=1;q.push(s);
    while(!q.empty())
    {
        nw=q.front(),q.pop();
        for(int i=hd[nw];i!=-1;i=nxt[i])
            if(!deep[to[i]]&&las[i]>0)deep[to[i]]=deep[nw]+1,q.push(to[i]);
    }
    return deep[t];
}
inline int dfs(int pos,int flow)
{
    if(pos==t)return flow;
    for(register int &i=cur[pos];i!=-1;i=nxt[i])
    {
        if(deep[to[i]]==deep[pos]+1&&las[i])
        {
            int nw=dfs(to[i],min(las[i],flow));
            if(nw>0)
            {
                las[i]-=nw,las[i^1]+=nw;
                return nw;
            }
        }
    }
    return 0;
}
void dinic()
{
    int flow=0,tmp;
    while(bfs())
    {
        for(register int i=0;i<=t;i++)cur[i]=hd[i];
        while(tmp=dfs(s,1e9))flow+=tmp;
    }
    cout<<n*n-m-flow;
}
int main()
{
    int x,y,id,vx,vy;
    memset(hd,-1,sizeof hd),
    memset(nxt,-1,sizeof nxt);
    scanf("%d%d",&n,&m);
    for(register int i=1;i<=m;i++)
    scanf("%d%d",&x,&y),vis[x][y]=1;
    for(register int i=1;i<=n;i++)
    for(register int j=1;j<=n;j++)
    {
        if(vis[i][j])continue;
        id=get(i,j);
        if((i+j)&1)add(s,id,1);else add(id,t,1);
        if((i+j)&1)
        for(register int k=0;k<8;k++)
        {
            vx=i+dx[k],vy=j+dy[k];
            if(vx<1||vx>n||vy<1||vy>n||vis[vx][vy])continue;
            add(id,get(vx,vy),1);
        }
    }
    dinic();
}

分配问题

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const int s=0,t=201;
int n,num=-1,hd[210],nxt[50010],to[50010],ww[50010],las[50010],cost[50010],dis[210],pre[210];bool inq[210];
void init()
{
    memset(nxt,-1,sizeof nxt);
    memset(hd,-1,sizeof hd);
}
void add_edge(int u,int v,int w,int c)
{
    nxt[++num]=hd[u],to[num]=v,cost[num]=c,
    las[num]=ww[num]=w,hd[u]=num;
}
bool spfa()
{
    queue<int>q;int nw;
    memset(inq,0,sizeof inq),
    memset(dis,127,sizeof dis),
    memset(pre,-1,sizeof pre);
    dis[s]=0,inq[s]=1,q.push(s);
    while(!q.empty())
    {
        nw=q.front(),q.pop(),inq[nw]=0;
        for(int i=hd[nw];i!=-1;i=nxt[i])
        {
            if(las[i]>0&&dis[to[i]]>dis[nw]+cost[i])
            {
                dis[to[i]]=dis[nw]+cost[i],pre[to[i]]=i;
                if(!inq[to[i]])q.push(to[i]);inq[to[i]]=1;
            }
        }
    }
    return dis[t]<=2e9;
}
void mcmf(int op)
{
    int flow,mnc=0;
    while(spfa())
    {
        flow=1e9;
        for(int i=pre[t];i!=-1;i=pre[to[i^1]])flow=min(flow,las[i]);
        for(int i=pre[t];i!=-1;i=pre[to[i^1]])las[i]-=flow,las[i^1]+=flow;
        mnc+=flow*dis[t];
    }
    printf("%d\n",mnc*op);
}
int main()
{
    int tmp;init();
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    add_edge(s,i,1,0),add_edge(i,s,0,0);
    for(int i=n+1;i<=2*n;i++)
    add_edge(i,t,1,0),add_edge(t,i,0,0);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        scanf("%d",&tmp),add_edge(i,n+j,1,tmp),add_edge(n+j,i,0,-tmp);
    }
    mcmf(1);
    for(int i=0;i<=num;i++)las[i]=ww[i],cost[i]=-cost[i];
    mcmf(-1);
}

运输问题

#include<bits/stdc++.h>
using namespace std;
const int s=0,t=201;
int hd[210],nxt[50010],to[50010],ww[50010],las[50010],cost[50010],num=-1,pre[210],dis[210];bool inq[210];
void add_edge(int u,int v,int w,int c)
{
    nxt[++num]=hd[u],to[num]=v,cost[num]=c,
    ww[num]=las[num]=w,hd[u]=num;
}
bool spfa()
{
    memset(dis,127,sizeof dis),
    memset(inq,0,sizeof inq),
    memset(pre,-1,sizeof pre);
    queue<int>q;int nw;
    dis[s]=0,inq[s]=1,q.push(s);
    while(!q.empty())
    {
        nw=q.front(),q.pop(),inq[nw]=0;
        for(int i=hd[nw];i!=-1;i=nxt[i])
        {
            if(las[i]>0&&dis[to[i]]>dis[nw]+cost[i])
            {
                dis[to[i]]=dis[nw]+cost[i],pre[to[i]]=i;
                if(!inq[to[i]])q.push(to[i]);inq[to[i]]=1;
            }
        }
    }
    return dis[t]<=1e9; 
}
void mcmf()
{
    int flow,mc=0;
    while(spfa())
    {
        flow=1e9;
        for(int i=pre[t];i!=-1;i=pre[to[i^1]])flow=min(flow,las[i]);
        for(int i=pre[t];i!=-1;i=pre[to[i^1]])las[i]-=flow,las[i^1]+=flow;
        mc+=dis[t]*flow;
    }
    printf("%d\n",abs(mc));
}
int main()
{
    int m,n,tmp;
    memset(nxt,-1,sizeof nxt),
    memset(hd,-1,sizeof hd);
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++)
    scanf("%d",&tmp),add_edge(s,i,tmp,0),add_edge(i,s,0,0);
    for(int i=1;i<=n;i++)
    scanf("%d",&tmp),add_edge(m+i,t,tmp,0),add_edge(t,m+i,0,0);
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&tmp);
            add_edge(i,j+m,1e9,tmp),add_edge(j+m,i,0,-tmp);
        }
    }
    mcmf();
    for(int i=0;i<=num;i++)las[i]=ww[i],cost[i]=-cost[i];
    mcmf();
}

负载平衡问题

#include<bits/stdc++.h>
using namespace std;
const int s=0,t=1050;
int hd[1100],nxt[20100],to[20100],las[20100],cost[20100],num=-1,dis[1100],pre[1100];bool inq[1100];
void add_edge(int u,int v,int w,int c)
{
    nxt[++num]=hd[u],to[num]=v,
    las[num]=w,cost[num]=c,hd[u]=num;
}
bool spfa()
{
    memset(dis,127,sizeof dis),
    memset(pre,-1,sizeof pre),
    memset(inq,0,sizeof inq);
    queue<int>q;int nw;
    dis[s]=0,inq[s]=1,q.push(s);
    while(!q.empty())
    {
        nw=q.front(),q.pop();inq[nw]=0;
        for(int i=hd[nw];i!=-1;i=nxt[i])
        {
            if(las[i]>0&&dis[to[i]]>dis[nw]+cost[i])
            {
                dis[to[i]]=dis[nw]+cost[i];pre[to[i]]=i;
                if(!inq[to[i]])q.push(to[i]);inq[to[i]]=1;
            }
        }
    }
    return dis[t]<=1e9;
}
void mcmf()
{
    int mc=0,flow;
    while(spfa())
    {
        flow=2e9;
        for(int i=pre[t];i!=-1;i=pre[to[i^1]])flow=min(flow,las[i]);
        for(int i=pre[t];i!=-1;i=pre[to[i^1]])las[i]-=flow,las[i^1]+=flow;
        mc+=flow*dis[t];
    }
    printf("%d",mc);
    return;
}
int main()
{
    int n,sum=0,tmp;
    memset(hd,-1,sizeof hd),
    memset(nxt,-1,sizeof nxt);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&tmp),add_edge(s,i,tmp,0),add_edge(i,s,0,0),sum+=tmp;sum/=n;
    for(int i=1;i<=n;i++)
    {
        add_edge(i,t,sum,0),add_edge(t,i,0,0);
        if(i>1)add_edge(i,i-1,1e9,1),add_edge(i-1,i,0,-1);
        if(i<n)add_edge(i,i+1,1e9,1),add_edge(i+1,i,0,-1);
    }
    add_edge(1,n,1e9,1),add_edge(n,1,0,-1),add_edge(n,1,1e9,1),add_edge(1,n,0,-1);
    mcmf();
}

二.其他

POJ-3281 Dining

一道需要拆点的题…

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;//F 1~100 N 101~200-201~300 D 301~400
const int s=0,t=505;
int hd[510],nxt[100010],las[100010],to[100010],num=-1,cur[510],deep[510];
void add(int u,int v,int w)
{
    nxt[++num]=hd[u],to[num]=v,las[num]=w,hd[u]=num,
    nxt[++num]=hd[v],to[num]=u,las[num]=0,hd[v]=num;
}
bool bfs()
{
    int nw;queue<int>q;
    memset(deep,0,sizeof deep);
    deep[s]=1,q.push(s);
    while(!q.empty())
    {
        nw=q.front(),q.pop();
        for(int i=hd[nw];i!=-1;i=nxt[i])
            if(las[i]>0&&!deep[to[i]])deep[to[i]]=deep[nw]+1,q.push(to[i]);
    }
    return deep[t];
}
int dfs(int pos,int flow)
{
    if(pos==t)return flow;
    int nw;
    for(int &i=cur[pos];i!=-1;i=nxt[i])
    {
        if(las[i]>0&&deep[to[i]]==deep[pos]+1)
        {
            nw=dfs(to[i],min(flow,las[i]));
            if(nw>0)
            {
                las[i]-=nw;
                las[i^1]+=nw;
                return nw;
            }
        }
    }
    return 0;
}
void dinic()
{
    int nw,flow=0;
    while(bfs())
    {
        for(int i=s;i<=t;i++)cur[i]=hd[i];
        while(nw=dfs(s,1e9))flow+=nw;
    }
    cout<<flow;
}
int main()
{
    int n,f,d,F,D,tmp;
    memset(hd,-1,sizeof hd);
    memset(nxt,-1,sizeof nxt);
    scanf("%d%d%d",&n,&f,&d);
    for(int i=1;i<=f;i++)
    add(s,i,1);
    for(int i=301;i<=300+d;i++)
    add(i,t,1);
    for(int i=101;i<=100+n;i++)
    add(i,i+100,1);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&F,&D);
        for(int j=1;j<=F;j++)
            scanf("%d",&tmp),add(tmp,i+100,1);
        for(int j=1;j<=D;j++)
            scanf("%d",&tmp),add(i+200,tmp+300,1);
    }
    dinic();
}

XJOI-线段的权

看不出是网络流的网络流..

在平面上有N条平行于Y轴的线段,每条线段都有一个权值,每次可以找出的Y轴上投影互不重叠的若干线段,求M次后,找出的线段最大权值和为多少。
N<=1000;M<=100;1<=Y1

#include<bits/stdc++.h>
using namespace std;
const int N=5010,s=0,t=5005,inf=1e9+7;
int to[20010],head[N+10],next[20010],las[20010],cost[20010],dis[20010],pre[N+10],num=-1;bool inq[N+10];
void add_edge(int u,int v,int w,int c)
{
    next[++num]=head[u],
    las[num]=w,to[num]=v,
    cost[num]=c,head[u]=num;
}
void init()
{
    memset(head,-1,sizeof head),
    memset(next,-1,sizeof next);
    for(int i=1;i<=N-1;i++)
    add_edge(i,i+1,inf,0),add_edge(i+1,i,0,0);
    return;
}
bool spfa()
{
    memset(inq,0,sizeof inq),
    memset(pre,-1,sizeof pre);
    memset(dis,127,sizeof dis);
    queue<int>q;int nw;
    dis[s]=0,inq[s]=1;q.push(s);
    while(!q.empty())
    {
        nw=q.front(),q.pop();inq[nw]=0;
        for(int i=head[nw];i!=-1;i=next[i])
        {
            if(las[i]&&dis[to[i]]>dis[nw]+cost[i])
            {
                dis[to[i]]=dis[nw]+cost[i],pre[to[i]]=i;
                if(!inq[to[i]])q.push(to[i]);inq[to[i]]=1;
            }
        }
    }
    return dis[t]<=1e9;
}
void mcmf()
{
    int flow=0,nw=0,spd=0;
    while(spfa())
    {
        nw=1e9;
        for(int i=pre[t];i!=-1;i=pre[to[i^1]])nw=min(nw,las[i]);
        for(int i=pre[t];i!=-1;i=pre[to[i^1]])las[i]-=nw,las[i^1]+=nw;
        flow+=nw,spd+=nw*dis[t];
    }
    printf("%d",-spd);
}
int main()
{
    int n,m,x,y1,y2,p;init();
    scanf("%d%d",&n,&m);
    add_edge(s,1,m,0),add_edge(1,s,0,0);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d",&x,&y1,&y2,&p);
        if(y1>y2)swap(y1,y2);
        add_edge(y1,y2,1,-p),add_edge(y2,y1,0,p);
    }
    mcmf();
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值