zoukankan      html  css  js  c++  java
  • P3254 圆桌问题

    题目描述

    假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri(i=1,2,,m)ri(i=1,2,……,m)

    会议餐厅共有n 张餐桌,每张餐桌可容纳ci(i=1,2,,n)ci(i=1,2,……,n)个代表就餐。

    为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。

    对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。

    输入输出格式

    输入格式:

    第1行有2个正整数m和n,m表示单位数,n表示餐桌数,1<=m<=150,1<=n<=270。

    第2行有m个正整数,分别表示每个单位的代表数。

    第3行有n个正整数,分别表示每个餐桌的容量。

    输出格式:

    如果问题有解,第1行输出1,否则输出0。接下来的m行给出每个单位代表的就餐桌号。如果有多个满足要求的方案,只要输出1个方案。

    输入输出样例





    输入样例#1:
    4 5
    4 5 3 5
    3 5 2 6 4

    输出样例#1:
    1
    1 2 4 5
    1 2 3 4 5
    2 4 5
    1 2 3 4 5

    题解:每个单位的人与每一个桌子都建立一个容量为00的边,每单位与原点建立容量为单位人数的边,每个桌子都与汇点建立容量为桌子人数的边,最后查看边被减为00的,既代表有人坐。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define inf 0x3f3f3f3f3f3f3f3f
    #define ll long long
    #define MAXN 30000
    using namespace std;
    int n;//点数、边数
    int X[MAXN],y[MAXN];
    int sp,tp;//原点、汇点
    struct node
    {
        int v,next;
        ll cap;
    }mp[MAXN*10];
    int pre[MAXN],dis[MAXN],cur[MAXN];//cur为当前弧优化,dis存储分层图中每个点的层数(即到原点的最短距离),pre建邻接表
    int cnt=0;
    void init()//不要忘记初始化
    {
        cnt=0;
        memset(pre,-1,sizeof(pre));
    }
    void add(int u,int v,int w)//加边
    {
        mp[cnt].v=v;
        mp[cnt].cap=w;
        mp[cnt].next=pre[u];
        pre[u]=cnt++;
        mp[cnt].v=u;
        mp[cnt].cap=0;
        mp[cnt].next=pre[v];
        pre[v]=cnt++;
    }
    bool bfs()//建分层图
    {
        memset(dis,-1,sizeof(dis));
        queue<int>q;
        while(!q.empty())
            q.pop();
        q.push(sp);
        dis[sp]=0;
        int u,v;
        while(!q.empty())
        {
            u=q.front();
            q.pop();
            for(int i=pre[u];i!=-1;i=mp[i].next)
            {
                v=mp[i].v;
                if(dis[v]==-1&&mp[i].cap>0)
                {
                    dis[v]=dis[u]+1;
                    q.push(v);
                    if(v==tp)
                        break;
                }
            }
        }
        return dis[tp]!=-1;
    }
    ll dfs(int u,ll cap)//寻找增广路
    {
        if(u==tp||cap==0)
            return cap;
        ll res=0,f;
        for(int &i=cur[u];i!=-1;i=mp[i].next)
        {
            int v=mp[i].v;
            if(dis[v]==dis[u]+1&&(f=dfs(v,min(cap-res,mp[i].cap)))>0)
            {
                mp[i].cap-=f;
                mp[i^1].cap+=f;
                res+=f;
                if(res==cap)
                    return cap;
            }
        }
        if(!res)
            dis[u]=-1;
        return res;
    }
    ll dinic()
    {
        ll ans=0;
        while(bfs())
        {
            for(int i=0;i<=n;i++)
                cur[i]=pre[i];
            ans+=dfs(sp,inf);
        }
        return ans;
    }
    int main()
    {
        init();
        int a,b,sum=0;
        scanf("%d%d",&a,&b);
        for (int i = 1; i <=a ; ++i) {
            scanf("%d",&X[i]);
            sum+=X[i];
        }
        for (int i = 1; i <=b ; ++i) {
            scanf("%d",&y[i]);
        }
        for (int i = 1; i <=a ; ++i) {
            for (int j = 1; j <=b ; ++j) {
                add(i,a+j,1);
            }
            add(0,i,X[i]);
        }
        for (int j = 1; j <=b ; ++j) {
            add(a+j,a+b+1,y[j]);
        }
        n=a+b+1;
        sp=0;tp=a+b+1;
        int k=dinic();
     //   printf("%d
    ",k);
        if(k==sum) printf("1
    ");
        else {printf("0
    ");return 0;}
        for (int i = 1; i <=a; ++i) {
            for (int j = pre[i]; j !=-1 ; j=mp[j].next) {
                if(mp[j].cap ==0) printf("%d ",mp[j].v-a);
            }
            printf("
    ");
        }
        return 0;
    }
    

      

  • 相关阅读:
    远程访问Linux的常见方式
    GIT的安装与使用
    01_c语言学习之gcc
    车轮——项目 --- 云笔记
    python 基于ubuntu16.04 建立虚拟环境
    利用msfvenom生成木马
    msfvenom参数简介
    kali linux修改更新源及更新
    记通过mysql数据库成功入侵到服务器内部的渗透实战
    UML 几种关系:泛化、关联
  • 原文地址:https://www.cnblogs.com/-xiangyang/p/9220230.html
Copyright © 2011-2022 走看看