• luoguP1402 酒店之王


    为了练dinic优化,再写一道网络流

    原题链接:

    https://www.luogu.org/problemnew/show/P1402

    写了很多非常辣鸡的代码还觉得挺对的我。。。

    题意简述:有n个顾客,m道菜,q个房间,顾客满意的条件是能吃到自己喜欢的菜,住自己满意的房间,求最多能让多少顾客满意。

    首先建边,源点连向所有的菜,菜向喜欢这道菜的顾客连一条边,顾客向他喜欢的房间连一条边,跑最大流即可。

    然而这是错的。

    为什么?假设有这个情况,一位顾客同时喜欢多个房间,但是很显然,他最多只能住一个房间,也就是流过这个顾客点的流量最大为1,这就是点流量的题了,解决方法就是把顾客拆开,一个只吃菜,一个只住房间(emmm...),然后在这个两个点之间连一条容量为1的边,这样再跑最大流就是对的了。

    点:

    房间  1--m
    人1   m+1--m+n
    人2   m+n+1--m+n<<1
    菜    m+n<<1+1--m+n<<1+q
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int inf=2147483647;
    void read(int &y)
    {
        y=0;char x=getchar();
        while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9')
        {
            y=y*10+x-'0';
            x=getchar();
        }
    }
    struct edge
    {
        int u,v,w;
    }e[100005];
    int n,m,q;
    int s,t=505,cnt=1;
    int head[1005],dis[1005];
    int min(int a,int b)
    {
        return a<b?a:b;
    }
    void add(int u,int v)
    {
        e[++cnt].u=head[u];e[cnt].v=v;
        e[cnt].w=1;head[u]=cnt;
        e[++cnt].u=head[v];e[cnt].v=u;
        e[cnt].w=0;head[v]=cnt;
    }
    int dfs(int x,int f)
    {
        if(x==t) return f;
        int d,tmp=0;
        for(int i=head[x];i!=-1;i=e[i].u)
        {
            int nxt=e[i].v;
            if(dis[nxt]==dis[x]+1&&e[i].w>0)
            {
                d=dfs(nxt,min(f-tmp,e[i].w));
                if(d==0) continue;
                e[i].w-=d;
                e[i^1].w+=d;
                tmp+=d;
                if(tmp==f) return tmp;
            }
        }
        if(!tmp) dis[x]=0;
        return tmp;
    }
    int bfs()
    {
        memset(dis,0,sizeof(dis));
        queue<int>q;
        q.push(0);dis[0]=1;
        while(!q.empty())
        {
            int tmp=q.front();q.pop();
            for(int i=head[tmp];i!=-1;i=e[i].u)
            {
                int p=e[i].v;
                if(dis[p]||e[i].w<=0) continue;
                dis[p]=dis[tmp]+1;
                q.push(p); 
            }
        }
        return dis[t];
    }
    int dinic()
    {
        int re=0;
        while(bfs()) re+=dfs(0,inf);
        return re;
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        read(n);read(m);read(q);
        int x;
        for(int i=1;i<=m;i++) add(s,i);
        for(int i=1;i<=n;i++) add(m+i,m+n+i);
        for(int i=1;i<=q;i++) add(m+(n<<1)+i,t);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                read(x);
                if(x==1) add(j,m+i);
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=q;j++)
            {
                read(x);
                if(x==1) add(m+n+i,m+(n<<1)+j);
            }
        }
        printf("%d",dinic());
        return 0;
    }
  • 相关阅读:
    Job流程:Shuffle详解
    学Python Django学得很迷茫,怎么办?-转自知乎
    URL补充
    创建多对多以及增加示例
    Day20-初识Ajax
    笔记-自己看Day20-待续
    Day20-单表中获取表单数据的3种方式
    Day19内容回顾
    一点疑惑的解释
    python os.path模块常用方法详解
  • 原文地址:https://www.cnblogs.com/zeroform/p/8495828.html
Copyright © 2020-2023  润新知