zoukankan      html  css  js  c++  java
  • POJ 3281 [网络流dinic算法模板]

    题意:

    农场主有f种食物,d种饮料,n头牛。

    接下来的n行每行第一个数代表第i头牛喜欢吃的食物数量,和第i头牛喜欢喝的饮料数目。

    接下来分别是喜欢的食物和饮料的编号。

    求解:农场主最多能保证几头牛同时能吃到喜欢的食物和喜欢的饮料。

    思路:

    从源点到每种食物加流量为1的边,保证每种食物只能被吃一次。

    将每头牛分为两个点,连一条流量为1的边,保证每头牛最多只能吃一份食物喝一份饮料。

    将每种饮料和汇点都进行连接,同样流量为1。

    将牛喜欢的食物和牛进行连边流量为1,将另一组代表牛的点和喜欢的饮料进行连边,同样流量为1。

    建好图之后就变成了最大流问题了。

    这里留一个用dinic解决最大流问题的模板。

    /*************************************************************************
           > File Name: T.cpp
           > Author: ttpond
           > Created Time: 2015-8-22 12:4:42
    ************************************************************************/
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<queue>
    #include<stack>
    #include<set>
    using namespace std;
    int z;
    int n,f,d;
    int pho[405][405];
    int dis[410];
    int nb;
    bool BFS()
    {
        nb++;
        int i,j;
        memset(dis,-1,sizeof(dis));
        int tmp;
        queue<int>q;
        dis[1]=0;
        q.push(1);
        while(!q.empty())
        {
            tmp=q.front();
            q.pop();
            for(int i=1; i<=z; i++)
            {
                if(dis[i]<0&&pho[tmp][i])
                {
                    dis[i]=dis[tmp]+1;
                    q.push(i);
                }
            }
        }
        if(dis[z]>0)
            return 1;
        else
            return 0;
    }
    int findans(int x,int low)
    {
        int i,a=0;
        if(x==z)
            return low;
        for(i=1; i<=z; i++)
        {
            if(pho[x][i]>0&&dis[i]==dis[x]+1&&(a=findans(i,min(low,pho[x][i]))))
            {
                pho[x][i]-=a;
                pho[i][x]+=a;
                return a;
            }
        }
        return 0;
    }
    int main()
    {
        int a,b,tmp;
        scanf("%d%d%d",&n,&f,&d);
        z=2+f+n*2+d;
        memset(pho,0,sizeof(pho));
        for(int i=2; i<=1+f; i++)
        {
            pho[1][i]=1;
        }
        for(int i=f+2; i<=f+n+1; i++)
        {
            pho[i][i+n]=1;
        }
        for(int i=2+f+n*2; i<=1+f+n*2+d; i++)
        {
            pho[i][2+f+n*2+d]=1;
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d",&a,&b);
            for(int j=1; j<=a; j++)
            {
                scanf("%d",&tmp);
                pho[tmp+1][i+f+1]=1;
            }
            for(int j=1; j<=b; j++)
            {
                scanf("%d",&tmp);
                pho[i+f+1+n][tmp+f+1+n*2]=1;
            }
        }
        int ans=0,tans;
        while(BFS())
        {
            while(tans=findans(1,0x7fffffff))
            {
                ans+=tans;
            }
        }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    最短路径之spfa
    最短路径之Bellman-Ford——解决负权边
    最短路径之Floyd-Warshall算法
    图上最短路径问题
    它们其实都是图(二分图)
    记忆化结果再利用 进一步探讨递推关系
    leetcode 376. 摆动序列 java
    leetcode 368. 最大整除子集 java
    leetcode 96. 不同的二叉搜索树 java
    leetcode 454. 四数相加 II java
  • 原文地址:https://www.cnblogs.com/tun117/p/4753033.html
Copyright © 2011-2022 走看看