• POJ1149(网络流)


    题意:有M个猪圈和N个顾客,最初猪圈是锁着的。每个顾客有其中的A把钥匙,需要买B头猪,顾客在买完猪便将门锁上,而且顾客是按照顺序来的。商家可以对开着的猪圈里面的猪进行任意调配,问最多可以卖出几头猪。

    构图:若该顾客是第一个来这个猪圈,则源向这个点连容量为猪圈猪数的边,否则从第一个来这个猪圈的顾客向他连容量无穷大的边,最大流。

    参考上交某退役神牛的文献:http://imlazy.ycool.com/post.2059102.html

    View Code
    /*Source Code
    
    Problem: 1149  User: HEU_daoguang
    Memory: 712K  Time: 32MS
    Language: G++  Result: Accepted
    
    Source Code*/
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    using namespace std;
    int m,n,a,b,key;
    struct Pig{
        int num,first;
    }p[1050];
    
    #define V 105
    #define E 10500
    #define inf 0xffff
    struct Edge{
        int u,v,c,next;
    }edge[E];
    int cnt;
    int dist[V];
    int head[V];
    int que[V];
    int sta[V];
    
    void init(){
        cnt=0;
        memset(head,-1,sizeof(head));
    }
    
    void addedge(int u,int v,int c){
        edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c;
        edge[cnt].next=head[u];head[u]=cnt++;
        edge[cnt].u=v;edge[cnt].v=u;edge[cnt].c=0;
        edge[cnt].next=head[v];head[v]=cnt++;
    }
    
    int dinic(int s,int t){
        int ans=0;
        while(true){
    
            int left,right,u,v;
            memset(dist,-1,sizeof(dist));
            left=right=0;
            que[right++]=s;
            dist[s]=0;
    
            while(left<right){
                u=que[left++];
                for(int k=head[u];k!=-1;k=edge[k].next){
                    u=edge[k].u;
                    v=edge[k].v;
                    if(edge[k].c>0 && dist[v]==-1){
                        dist[v]=dist[u]+1;
                        que[right++]=v;
    
                        if(v==t){
                            left=right;
                            break;
                        }
                    }
                }
    
            }
    
            if(dist[t]==-1) break;
    
            int top=0;
            int now=s;
            while(true){
                if(now!=t){
                    int k;
                    for(k=head[now];k!=-1;k=edge[k].next){
                        if(edge[k].c>0 && dist[edge[k].v]==dist[edge[k].u]+1) break;
                    }
                    if(k!=-1){
                        sta[top++]=k;
                        now=edge[k].v;
                    }
                    else{
                        if(top==0) break;
                        dist[edge[sta[--top]].v]=-1;
                        now=edge[sta[top]].u;
                    }
                }
                else{
                    int flow=inf,ebreak;
                    for(int i=0;i<top;i++){
                        if(flow>edge[sta[i]].c){
                            flow=edge[sta[i]].c;
                            ebreak=i;
                        }
                    }
                    ans+=flow;
                    for(int i=0;i<top;i++){
                        edge[sta[i]].c-=flow;
                        edge[sta[i]^1].c+=flow;
                    }
                    now=edge[sta[ebreak]].u;
                    top=ebreak;
                }
            }
    
        }
        return ans;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(scanf("%d%d",&m,&n)!=EOF){
            for(int i=1;i<=m;i++){
                scanf("%d",&p[i].num);
                p[i].first=0;
            }
            init();
            for(int i=1;i<=n;i++){
                scanf("%d",&a);
                for(int j=1;j<=a;j++){
                    scanf("%d",&key);
                    if(p[key].first==0){
                        addedge(0,i,p[key].num);
                        p[key].first=i;
                    }
                    else{
                        addedge(p[key].first,i,inf);
                    }
                }
                scanf("%d",&b);
                addedge(i,n+1,b);
            }
            printf("%d\n",dinic(0,n+1));
        }
        return 0;
    }

    卡了两点:1.在dfs找增广路中最小权值边时,模板打错了,没有在dfs栈中找,导致“黑洞”。 2.忘初始化了,导致"黑洞"。

    通过神牛的文献中学习到了一些建图及优化的思路:

    “在面对网络流问题时,如果一时想不出很好的构图方法,不如先构造一个最直观,或者说最“硬来”的模型,然后再用合并节点和边的方法来简直化这个模型。经过简化以后,好的构图思路自然就会涌现出来了。这是解决网络流问题的一个好方法。”

  • 相关阅读:
    函数指针
    回调函数
    内核文件ntoskrnl.exe,ntkrnlpa.exe的区别??
    单引号和0的ASCII码
    文件句柄和句柄
    ObReferenceObjectByName蓝屏问题
    DbgPrint/KdPrint输出格式控制
    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
    Mac中SVN的常见命令
    小程序分包加载实现代码包总上限8M
  • 原文地址:https://www.cnblogs.com/markliu/p/2508952.html
Copyright © 2020-2023  润新知