hdu4292 Food 最大流模板题

Posted a_clown_cz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

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;
}

 

以上是关于hdu4292 Food 最大流模板题的主要内容,如果未能解决你的问题,请参考以下文章

HDU-4292-Food(最大流,Dinic)

HDU 4292 Food(最大流)

HDU 4292 Food (拆点最大流)

HDU 4292 Food (建图思维 + 最大流)

[hdu4292] Food [网络流]

HDU 4292 FOOD