zoukankan      html  css  js  c++  java
  • SCUT

    https://scut.online/p/205
    连着做所以一开始就觉得是网络流。
    这种至多分配几次的很有网络流的特征。

    一开始想从食物和饮料流向牛,但是怎么搞都不对。
    其实可以从s流向食物,食物流向牛,牛流向饮料,饮料流向t。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    
    namespace Dinic_Maxflow {
    
        /* 备注:
        1.检查MAXN与MAXM,注意预留反向边和额外边的位置
        2.每次建图的第一次add_edge()前必须先init()
        3.不传入第三参数的dinic(s,t)需保证t是最后的结点
         */
    
        const int INF=0x3f3f3f3f;
    
        const int MAXN=2000;
        const int MAXM=200000;
        //注意网络流要预留反向边
    
        int tol;
        int head[MAXN+5];
    
        struct Edge {
            int to,next,cap,flow;
        } edge[MAXM+5];
    
    
        void init() {
            //.//用来触发编译错误
            tol=2;
            memset(head,-1,sizeof(head));
        }
    
        //为了方便使用二分图匹配,默认容量为1,默认反向容量为0
        void add_edge(int u,int v,int w=1,int rw=0) {
            edge[tol].to=v;
            edge[tol].cap=w;
            edge[tol].flow=0;
            edge[tol].next=head[u];
            head[u]=tol++;
            edge[tol].to=u;
            edge[tol].cap=rw;
            edge[tol].flow=0;
            edge[tol].next=head[v];
            head[v]=tol++;
        }
    
        int Q[MAXN+5];
        int dep[MAXN+5],cur[MAXN+5],sta[MAXN+5];
    
        bool bfs(int s,int t) {
            //front 与 back 的缩写
            int fnt=0,bak=0;
            memset(dep,-1,sizeof(dep[0])*(t+1));
            dep[s]=0;
            Q[bak++]=s;
            while(fnt<bak) {
                int u=Q[fnt++];
                for(int i=head[u]; i!=-1; i=edge[i].next) {
                    int v=edge[i].to;
                    if(dep[v]==-1&&edge[i].cap>edge[i].flow) {
                        dep[v]=dep[u]+1;
                        if(v==t)
                            return true;
                        Q[bak++]=v;
                    }
                }
            }
            return false;
        }
    
        int dinic(int s,int t) {
            int maxflow=0;
            while(bfs(s,t)) {
                for(int i=0; i<=t; i++)
                    cur[i]=head[i];
                int u=s,tail=0;
                while(cur[s]!=-1) {
                    if(u==t) {
                        int tp=INF;
                        for(int i=tail-1; i>=0; i--) {
                            tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                        }
                        maxflow+=tp;
                        for(int i=tail-1; i>=0; i--) {
                            edge[sta[i]].flow+=tp;
                            edge[sta[i]^1].flow-=tp;
                            if(edge[sta[i]].cap-edge[sta[i]].flow==0)
                                tail=i;
                        }
                        u=edge[sta[tail]^1].to;
                    } else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow
                              &&dep[u]+1==dep[edge[cur[u]].to]) {
                        sta[tail++]=cur[u];
                        u=edge[cur[u]].to;
                    } else {
                        while(u!=s&&cur[u]==-1) {
                            u=edge[sta[--tail]^1].to;
                        }
                        cur[u]=edge[cur[u]].next;
                    }
                }
            }
            return maxflow;
        }
    
        /* 备注:
        1.检查MAXN与MAXM,注意预留反向边和额外边的位置
        2.每次建图的第一次addedge()前必须先init()
        3.不传入第三参数的dinic(s,t)需保证t是最后的结点
         */
    
    }
    
    
    using namespace Dinic_Maxflow;
    
    int n,f,d;
    inline int id(char type,int x) {
        int res=0;
        switch(type) {
            case 'n':
                return x;
            case 'f':
                return n+x;
            case 'd':
                return n+f+x;
            default:
                exit(-1);
        }
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in","r",stdin);
    #endif // Yinku
        while(~scanf("%d%d%d",&n,&f,&d)) {
            init();
            int s=0,t=n+f+d+1;
            for(int i=1;i<=f;i++){
                add_edge(s,id('f',i),1);
            }
            for(int i=1;i<=d;i++){
                add_edge(id('d',i),t,1);
            }
            for(int i=1; i<=n; i++) {
                int fi,di;
                scanf("%d%d",&fi,&di);
                int u=id('n',i);
                for(int j=1;j<=fi;j++){
                    int v;
                    scanf("%d",&v);
                    v=id('f',v);
                    add_edge(v,u,1);
                }
                for(int j=1;j<=di;j++){
                    int v;
                    scanf("%d",&v);
                    v=id('d',v);
                    add_edge(u,v,1);
                }
            }
    
            printf("%d
    ",dinic(s,t));
        }
    }
    
  • 相关阅读:
    hadoop学习笔记(十):MapReduce工作原理(重点)
    hadoop学习笔记(九):MapReduce程序的编写
    hadoop学习笔记(八):MapReduce
    hadoop学习笔记(七):Java HDFS API
    hadoop学习笔记(六):HDFS文件的读写流程
    hadoop学习笔记(五):HDFS Shell命令
    hadoop学习笔记(四):HDFS
    hadoop学习笔记(三):hadoop文件结构
    立即执行函数
    let命令
  • 原文地址:https://www.cnblogs.com/Yinku/p/11024942.html
Copyright © 2011-2022 走看看