zoukankan      html  css  js  c++  java
  • 【洛谷P3254】【24题】圆桌问题【网络流】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P3254
    nn个餐桌mm个公司,每个公司有a[i]a[i]个人,而每个餐桌能容纳b[i]b[i]人。同一个公司的人不能坐在一个餐桌上。求能否满足以上要求。


    思路:

    卡时卡过的,也不知道为什么会被卡。
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这道题很明显最大流。公司放左边,桌子放右边,原点连公司,流量为公司人数,汇点连桌子,流量为可以容纳的人数。所有公司依次和所有桌子相连,流量为1。
    然后跑一边最大流即可。


    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define INF 1e9
    using namespace std;
    
    int n,m,k,head[800001],dep[800001],s,t,x,sum,num,ans,p[501][801],peo[801];
    
    struct edge
    {
        int next,c,to;
    }e[2000001];
    
    void add(int from,int to,int c)  //建模
    {
        k++;
        e[k].to=to;
        e[k].c=c;
        e[k].next=head[from];
        head[from]=k;
    }
    
    bool bfs()  //分层
    {
        memset(dep,0x3f3f3f3f,sizeof(dep));
        queue<int> q;
        q.push(s);
        dep[s]=0;
        while (q.size())
        {
            int u=q.front();
            q.pop();
            for (int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to;
                if (dep[v]>dep[u]+1&&e[i].c)
                {
                    dep[v]=dep[u]+1;
                    q.push(v);
                }
            }
        }
        return (dep[t]<0x3f3f3f3f);
    }
    
    int dfs(int u,int low)  //找增广路
    {
        int lows=0;
        if (u==t) return low;
        for (int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if (dep[v]==dep[u]+1&&e[i].c)
            {
                lows=dfs(v,min(low,e[i].c));
                if (!lows) continue;
                e[i].c-=lows;
                e[i^1].c+=lows;
                return lows;
            }
        }
        return 0;
    }
    
    void print()  //输出方案
    {
        for (int i=n+1;i<=n+m;i++)
         for (int j=head[i];j;j=e[j].next)
         {
            int v=e[j].to;
            if (v<t&&e[j].c)
             p[v][++peo[v]]=i-n;  //每个公司的人坐的餐桌
         }
        for (int i=1;i<=n;i++)
        {
        	for (int j=1;j<=peo[i];j++)
          	 printf("%d ",p[i][j]);
          	printf("\n");
        } 
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        k=1;
        s=n+m+10;
        t=n+m+11;
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            num+=x;
            add(s,i,x);
            add(i,s,0);
            for (int j=n+1;j<=n+m;j++)
            {
                add(i,j,1);
                add(j,i,0);
            }
        }
        for (int i=1;i<=m;i++)
        {
            scanf("%d",&x);
            add(n+i,t,x);
            add(t,n+i,0);
        }
        while (bfs())
        {	
            while (sum=dfs(s,INF))
             ans+=sum;
        }
        if (ans<num) return printf("0\n")&0;
        printf("1\n");
        print();
        return 0;
    }
    
  • 相关阅读:
    Java 标识符
    Java 关键字详解
    Java 语言的主要特性
    redis学习
    垃圾回收
    JVM内存结构
    sql总结(DML)
    sql总结(DDL)
    加密算法
    《数据结构》 定长顺序串常用操作代码集合
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998638.html
Copyright © 2011-2022 走看看