1. 程式人生 > >Dining POJ

Dining POJ

  • 題意:一些牛,每隻牛有 一些  想吃的food and milk,然後問最大能夠滿足多少隻牛。
  • 滿足是指的這頭牛即能吃到他喜歡吃的又能喝到他喜歡喝的
  • 思路:最大流,關鍵建出圖來,源點匯點肯定是要有的,然後中間呢因為滿足一頭牛的需求是有一個food and milk
  • 所以為了保證結果最大隻需要經過每個牛一次就行了,這裡就需要把牛copy一遍中間自己到自己連一條邊權為1的邊
  • 而且 為了 達到 "滿足“這個效果 很明顯不能把food and milk 放在一遍 ,需要用牛在中間把他們隔開。
  • 整體上一條流量是這樣的 :源點——food——牛——牛——milk——匯點

  • #include<stdio.h>
    #include<cstring>
    #include<queue>
    using namespace std;
    #define maxn 10005
    #define inf 0x3f3f3f3f
    struct node
    {
        int to,v,w;
    } edge[maxn*20];
    int head[maxn],totlen,f;
    int level[maxn],s,t,n,d;
    int sum,orz,QYN,cnt=-1;
    void add(int x,int y,int z)
    {
        edge[++cnt].to=head[x];
        head[x]=cnt;
        edge[cnt].v=y;
        edge[cnt].w=z;
        edge[++cnt].to=head[y];
        head[y]=cnt;
        edge[cnt].v=x;
        edge[cnt].w=0;
    }
    bool dinic_bfs()
    {
        memset(level,0,sizeof(level));
        queue<int>que;
        que.push(0);
        level[0]=1;
        while(!que.empty())
        {
            int u=que.front();
            que.pop();
            for(int i=head[u]; i!=-1; i=edge[i].to)
            {
                int v=edge[i].v;
                if(!level[v]&&edge[i].w>0)
                {
                    level[v]=level[u]+1;
                    que.push(v);
                }
            }
        }
        return level[sum]!=0;
    }
    int dinic_dfs(int u,int cpflow)
    {
        if(u==sum)return cpflow;
        int addflow=0;
        for(int i=head[u]; i!=-1&&addflow<cpflow; i=edge[i].to)
        {
            int v=edge[i].v;
            if(level[u]+1==level[v]&&edge[i].w>0)
            {
                int temp=dinic_dfs(v,min(cpflow-addflow,edge[i].w));
                edge[i].w-=temp;
                edge[i^1].w+=temp;
                addflow+=temp;
            }
        }
        return addflow;
    }
    void  dinic()
    {
        int maxflow=0;
        while(dinic_bfs())
            maxflow+=dinic_dfs(0,sum);
        printf("%d\n",maxflow);
    }
    int main()
    {
        scanf("%d%d%d",&n,&f,&d);
        sum=n+f+d+n+1;
        int s1=n+f+n,s2=n+f,s3=f;
        memset(head,-1,sizeof(head));
        for(int i=1; i<=f; i++)
            add(0,i,1);
        for(int i=1; i<=n; i++)
            add(i+s3,i+s2,1);
        for(int i=1; i<=d; i++)
            add(s1+i,sum,1);
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d",&f,&d);
            while(f--)
            {
                scanf("%d",&orz);
                add(orz,s3+i,1);
            }
            while(d--)
            {
                scanf("%d",&orz);
                add(s2+i,s1+orz,1);
            }
        }
        dinic();
        return 0;
    }