dinic网络最大流

本文深入探讨了最大流问题中的Dinic算法实现,并通过一个具体的编程示例展示了如何使用该算法来解决实际问题。文章首先引入了必要的数据结构定义,接着详细讲解了BFS和DFS在构造层次图和寻找增广路径中的应用。

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

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>

using namespace std;

const int inf=0x7fffffff;

int n,m,t,cnt;

struct zp
{
    int u,v,w,Next;
}Map[1000010];

int dis[1010],head[1010];

void add(int u,int v,int w)
{
    Map[cnt].u=u; Map[cnt].v=v; Map[cnt].w=w;
    Map[cnt].Next=head[u]; head[u]=cnt++;
    Map[cnt].u=v; Map[cnt].v=u; Map[cnt].w=0;
    Map[cnt].Next=head[v]; head[v]=cnt++;
}

int BFS()//根据残留网络建立层次图     起点为0记得改
{
    memset(dis,0,sizeof(dis));
    dis[0]=1;
    queue<int> q;
    q.push(0);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u]; i!=-1; i=Map[i].Next)
        {
            int v=Map[i].v;
            if(Map[i].w&&!dis[v])
            {
                dis[v]=dis[u]+1;
                if(v==t)
                    return 1;
                q.push(v);
            }
        }
    }
        return 0;
}

int dfs(int a,int low)//寻找增广路
{
    int cost=0;
    if(a==t) return low;
    for(int i=head[a]; i!=-1; i=Map[i].Next)
    {
        int v=Map[i].v;
        if(Map[i].w&&dis[a]==dis[v]-1)
        {
            int tmp=dfs(v,min(low-cost,Map[i].w));
            if(tmp>0)
            {
                Map[i].w-=tmp;
                Map[i^1].w+=tmp;//反向边
                cost+=tmp;
                if(cost==low)
                    break;
            }
            else
            dis[v]=-1;
        }
    }
    return cost;
}

int dinic()//求最大流
{
    int ans=0,s=0;//s为起点
    while(BFS())
        ans+=dfs(s,inf);
    return ans;
}
int main()
{
    int ncase,s[505],e[505],p[505];
    scanf("%d",&ncase);
    int cas=1;
    while(ncase--)
    {
        scanf("%d%d",&n,&m);
        int t1=n,t2=0,sum=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d%d",&p[i],&s[i],&e[i]);
            t1=min(t1,s[i]);
            t2=max(t2,e[i]);
            sum+=p[i];
        }
        cnt=0;
        memset(head,-1,sizeof(head));
        for(int i=t1;i<=t2;i++)
        {
            add(0,i,m);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=s[i];j<=e[i];j++)
            {
                add(j,j+t2,1);
                add(j+t2,2*t2,1);
            }
        }
        t=2*t2;
        if(sum<=dinic())
            printf("Case %d: Yes\n\n",cas++);
        else
            printf("Case %d: No\n\n",cas++);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值