hdu4292 Food 最大流模板题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4292

题意:水和饮料,建图跑最大流模板。

我用的是学长的模板,最然我还没有仔细理解,不过这都不重要直接贴就行了。

下面是AC代码,以后就当做最大流的模板来用了。

代码:

#include<cstdio>
#include<iostream>
using namespace std;

const int oo=1e9;
const int mm=2e5+5;
const int mn=1e5+5;

int node,src,dest,edge;
int ver[mm],flow[mm],Next[mm];
int head[mn],work[mn],dis[mn],q[mn];

int Min(int a,int b)
{
    return a<b?a:b;
}

void prepare(int _node,int _src,int _dest)
{
    node=_node,src=_src,dest=_dest;
    for(int i=0; i<node; ++i)head[i]=-1;
    edge=0;
}


void Addedge(int u,int v,int c)
{
    ver[edge]=v,flow[edge]=c,Next[edge]=head[u],head[u]=edge++;
    ver[edge]=u,flow[edge]=0,Next[edge]=head[v],head[v]=edge++;
}

bool Dinic_bfs()
{
    int i,u,v,l,r=0;
    for(i=0; i<node; ++i)dis[i]=-1;
    dis[q[r++]=src]=0;
    for(l=0; l<r; ++l)
        for(i=head[u=q[l]]; i>=0; i=Next[i])
            if(flow[i]&&dis[v=ver[i]]<0)
            {
                dis[q[r++]=v]=dis[u]+1;
                if(v==dest)return 1;
            }
    return 0;
}

int Dinic_dfs(int u,int exp)
{
    if(u==dest)return exp;
    for(int &i=work[u],v,tmp; i>=0; i=Next[i])
        if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,Min(exp,flow[i])))>0)
        {
            flow[i]-=tmp;
            flow[i^1]+=tmp;
            return tmp;
        }
    return 0;
}

int Dinic_flow()
{
    int i,ret=0,delta;
    while(Dinic_bfs())
    {
        for(i=0; i<node; ++i) work[i]=head[i];
        while(delta=Dinic_dfs(src,oo)) ret+=delta;

    }
    return ret;
}


int main()
{
    char s[205];
    int n,f,d,t;
    while(scanf("%d%d%d",&n,&f,&d)==3)
    {
        prepare(n*2+f+d+2,0,n*2+f+d+1);
        for(int i=1; i<=f; i++)
        {
            scanf("%d",&t);
            Addedge(0,i,t);///源点加边
        }
        for(int i=1; i<=d; i++)
        {
            scanf("%d",&t);
            Addedge(f+2*n+i,f+2*n+d+1,t);///汇点加边
        }
        for(int i=1; i<=n; i++)
            Addedge(f+i,f+n+i,1);///拆点
        for(int i=1; i<=n; i++)
        {
            scanf("%s",s+1);
            for(int j=1; j<=f; j++)
                if(s[j]=='Y')
                    Addedge(j,f+i,1);///顾客与食物加边
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%s",s+1);
            for(int j=1; j<=d; j++)
                if(s[j]=='Y')
                    Addedge(f+n+i,f+2*n+j,1);///顾客与饮料加边
        }
        printf("%d\n",Dinic_flow());
    }
    return 0;
}

学长模板的链接:http://m.blog.csdn.net/article/details?id=30030439

 模板:

#include<cstdio>
#include<iostream>
using namespace std;
const int oo=1e9;

const int mm=111111;
const int mn=999;
int node,src,dest,edge;
int ver[mm],flow[mm],next[mm];
int head[mn],work[mn],dis[mn],q[mn];


void prepare(int _node,int _src,int _dest) ///node是结点总数
{
    node=_node,src=_src,dest=_dest;
    for(int i=0; i<node; ++i)head[i]=-1;
    edge=0;
}

void addedge(int u,int v,int c)
{
    ver[edge]=v,flow[edge]=c,next[edge]=head[u],head[u]=edge++;
    ver[edge]=u,flow[edge]=0,next[edge]=head[v],head[v]=edge++;
}

bool Dinic_bfs()
{
    int i,u,v,l,r=0;
    for(i=0; i<node; ++i)dis[i]=-1;
    dis[q[r++]=src]=0;
    for(l=0; l<r; ++l)
        for(i=head[u=q[l]]; i>=0; i=next[i])
            if(flow[i]&&dis[v=ver[i]]<0)
            {
                dis[q[r++]=v]=dis[u]+1;
                if(v==dest)return 1;
            }
    return 0;
}

int Dinic_dfs(int u,int exp)
{
    if(u==dest)return exp;
    for(int &i=work[u],v,tmp; i>=0; i=next[i])
        if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
        {
            flow[i]-=tmp;
            flow[i^1]+=tmp;
            return tmp;
        }
    return 0;
}
int Dinic_flow()
{
    int i,ret=0,delta;
    while(Dinic_bfs())
    {
        for(i=0; i<node; ++i)work[i]=head[i];
        while(delta=Dinic_dfs(src,oo))ret+=delta;
    }
    return ret;
}

SAP模板:

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;

const int MAXN=1005;//点数的最大值
const int MAXM=1005*1005*4;//边数的最大值
const int INF=0x3f3f3f3f;

struct Edge
{
    int to,next,cap,flow;
} edge[MAXM]; //注意是MAXM

int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];

void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}
//加边,单向图三个参数,双向图四个参数
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to = v;
    edge[tol].cap = w;
    edge[tol].next = head[u];
    edge[tol].flow = 0;
    head[u] = tol++;

    edge[tol].to = u;
    edge[tol].cap = rw;
    edge[tol].next = head[v];
    edge[tol].flow = 0;
    head[v]=tol++;
}
//输入参数:起点、终点、点的总数
//点的编号没有影响,只要输入点的总数
int sap(int start,int end,int N)
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    int u=start;
    pre[u]=-1;
    gap[0]=N;
    int ans=0;
    while(dep[start]<N)
    {
        if(u==end)
        {
            int Min=INF;
            for(int i=pre[u]; i!=-1; i=pre[edge[i^1].to])
                if(Min>edge[i].cap-edge[i].flow)
                    Min=edge[i].cap-edge[i].flow;
            for(int i=pre[u]; i!=-1; i=pre[edge[i^1].to])
            {
                edge[i].flow+=Min;
                edge[i^1].flow-=Min;
            }
            u=start;
            ans+=Min;
            continue;
        }
        bool flag=false;
        int v;
        for(int i=cur[u]; i!=-1; i=edge[i].next)
        {
            v=edge[i].to;
            if(edge[i].cap-edge[i].flow && dep[v]+1==dep[u])
            {
                flag=true;
                cur[u]=pre[v]=i;
                break;
            }
        }
        if(flag)
        {
            u=v;
            continue;
        }
        int Min=N;
        for(int i=head[u]; i!=-1; i=edge[i].next)
            if(edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
            {
                Min=dep[edge[i].to];
                cur[u]=i;
            }
        gap[dep[u]]--;
        if(!gap[dep[u]])return ans;
        dep[u]=Min+1;
        gap[dep[u]]++;
        if(u!=start) u=edge[pre[u]^1].to;
    }
    return ans;
}

int main()
{
    init();
    addedge(u,v,value);
    maxf=sap(0,n+m+1,n+m+2); ///源点,汇点,总点数的值。
}

 

ISAP模板:

#include <cstdio>
#include <cstring>

using namespace std;

const int MAXN = 2010;
const int MAXM = 800000;

// ISAP

struct edge
{
    int t, f;
    edge *p, *r;
} T[MAXM], *H[MAXN], *I[MAXN], *P[MAXN];

int C;
int G[MAXN], D[MAXN], L[MAXN];


inline void adde(const int a, const int b, const int c)
{
    edge *e1 = T + C++;
    edge *e2 = T + C++;
    e1->t = b;
    e1->f = c;
    e1->p = H[a];
    e1->r = e2;
    H[a] = e1;
    e2->t = a;
    e2->f = 0;
    e2->p = H[b];
    e2->r = e1;
    H[b] = e2;
}

inline int isap(const int cnt, const int src, const int snk)
{
    int maxf = 0;
    int curf = 0x3f3f3f3f;
    int u = src, v;
    edge *e;
    memcpy(I, H, sizeof(H));
    memset(G, 0, sizeof(G));
    memset(D, 0, sizeof(D));
    G[0] = cnt;
    while (D[src] < cnt)
    {
        L[u] = curf;
        for (e = I[u]; e; e = e->p)
        {
            v = e->t;
            if (e->f > 0 && D[u] == D[v] + 1)
            {
                I[u] = P[v] = e;
                if (e->f < curf)
                    curf = e->f;
                u = v;
                if (u == snk)
                {
                    maxf += curf;
                    while (u != src)
                    {
                        P[u]->f -= curf;
                        P[u]->r->f += curf;
                        u = P[u]->r->t;
                    }
                    curf = 0x3f3f3f3f;
                }
                break;
            }
        }
        if (e)
            continue;
        if (!--G[D[u]])
            break;
        int mind = cnt - 1;
        for (e = H[u]; e; e = e->p)
            if (e->f > 0 && D[e->t] < mind)
            {
                I[u] = e;
                mind = D[e->t];
            }
        ++G[D[u] = mind + 1];
        if (u != src)
        {
            u = P[u]->r->t;
            curf = L[u];
        }
    }
    return maxf;
}

int N, M;
bool V[500];

int main()
{
    int tt, a, b, c, ss, cnt;
    scanf("%d", &tt);
    for (int tc = 1; tc <= tt; ++tc)
    {
        memset(V, false, sizeof(V));
        memset(H, 0, sizeof(H));
        ss = 0;
        C = 0;
        scanf("%d%d", &N, &M);
        cnt = N + 2;
        for (int i = 0; i < N; ++i)
        {
            scanf("%d%d%d", &a, &b, &c);
            adde(2004, i, a);
            for (int j = b - 1; j < c; ++j)
            {
                adde(i, j + 1000, 1);
                if (!V[j])
                {
                    adde(j + 1000, 2005, M);
                    V[j] = true;
                    ++cnt;
                }
            }
            ss += a;
        }
        if (isap(cnt, 2004, 2005) == ss)
            printf("Case %d: Yes\n\n", tc);
        else
            printf("Case %d: No\n\n", tc);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/a-clown/p/6536196.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值