zoukankan      html  css  js  c++  java
  • 网络流24题-圆桌问题

    圆桌问题

    时空限制1000ms / 128MB

    题目描述

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

    会议餐厅共有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 个方案。

    输入输出样例

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

    二分图多重最大匹配。
    参考博客:https://blog.csdn.net/luozhong11/article/details/52430572

    在二分图最大匹配中,每个点(不管是X点还是Y点)最多只能和一条匹配边相关联,然而,我们经常遇到这种问题,即二分图匹配中一个点可以和多条匹配边相关联,但有上限,或者说,Li表示点i最多可以和多少条匹配边相关联。

    二分图多重匹配分为二分图多重最大匹配与二分图多重最优匹配两种,分别可以用最大流与最大费用最大流解决。

    (1)二分图多重最大匹配:
    在原图上建立源点S和汇点T,S向每个X点连一条容量为该X点L值的边,每个Y点向T连一条容量为该Y点L值的边,原来二分图中各边在新的网络中仍存在,容量为1(若该边可以使用多次则容量大于1),求该网络的最大流,就是该二分图多重最大匹配的值。

    (2)二分图多重最优匹配:
    在原图上建立源点S和汇点T,S向每个X点连一条容量为该X点L值、费用为0的边,每个Y点向T连一条容量为该Y点L值、费用为0的边,原来二分图中各边在新的网络中仍存在,容量为1(若该边可以使用多次则容量大于1),费用为该边的权值。求该网络的最大费用最大流,就是该二分图多重最优匹配的值。

    #include<bits/stdc++.h>
    #define N 520
    using namespace std;
    typedef struct
    {
        int v;
        long long flow;
    }ss;
    
    ss edg[N*N];
    vector<int>edges[N];
    int now_edges=0;
    long long fl[N][N]={0};
    
    void addedge(int u,int v,long long flow)
    {
        fl[u][v]+=flow;
        edges[u].push_back(now_edges);
        edg[now_edges++]=(ss){v,flow};
        edges[v].push_back(now_edges);
        edg[now_edges++]=(ss){u,0};
    }
    
    int dis[N],S,T;
    bool bfs()
    {
        memset(dis,0,sizeof(dis));
        queue<int>q;
        q.push(S);
        dis[S]=1;
        
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
            int Size=edges[now].size();
            
            for(int i=0;i<Size;i++)
            {
                ss e=edg[edges[now][i]];
                if(e.flow>0&&dis[e.v]==0)
                {
                    dis[e.v]=dis[now]+1;
                    q.push(e.v);
                }
            }
        }    
        if(dis[T]==0)return 0;
        return 1;
        
    }
    int current[N];
    long long dfs(int now,long long maxflow)
    {
        if(now==T)return maxflow;
        int Size=edges[now].size();
        for(int i=current[now];i<Size;i++)
        {
            current[now]=i;
            ss &e=edg[edges[now][i]];
            
            if(e.flow>0&&dis[e.v]==dis[now]+1)
            {
                long long Flow=dfs(e.v,min(maxflow,e.flow));
                
                if(Flow)
                {
                    fl[now][e.v]-=Flow;
                    fl[e.v][now]+=Flow;
                    
                    e.flow-=Flow;
                    edg[edges[now][i]^1].flow+=Flow;
                    return Flow;
                }
            }
        }
        return 0;
    }
    
    long long dinic()
    {
        long long ans=0,flow;
        while(bfs())
        {
            memset(current,0,sizeof(current));
            while(flow=dfs(S,LLONG_MAX/2))ans+=flow;
        }
        return ans;
    }
    
    int main()
    {
        int m,n;
        long long sum=0;
        int present[N],desk[N];
        scanf("%d %d",&m,&n);
        for(int i=1;i<=m;i++)scanf("%d",&present[i]),sum+=present[i];
        for(int i=1;i<=n;i++)scanf("%d",&desk[i]);
        
        S=n+m+1;
        T=n+m+2;
    
        for(int i=1;i<=m;i++)addedge(S,i,present[i]);
        for(int i=1;i<=n;i++)addedge(i+m,T,desk[i]);
    
        for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
        addedge(i,j+m,1);
        
        long long ans=dinic();
        
        if(sum==ans)
        {
            printf("1
    ");
            for(int i=1;i<=m;i++)
            {
                for(int j=1;j<=n;j++)
                if(fl[j+m][i])printf("%d ",j);
                printf("
    ");
            }
        }
        else
        printf("0
    ");
        return 0;
        
    }
    View Code
  • 相关阅读:
    Great StackOverflow questions
    通过cdn引用的js
    iphone中点击input不能选中input中的内容
    php创建文件默认所属用户和组
    在Linux下php连接mysql数据库遇到2002错误
    一些命令的参数作用
    ubuntu安装完成之后wifi无法连接
    根据MAC地址获取网络地址及ZDP_NwkAddrReq函数的用法
    结合MeteoInfo开发WinformGIS系统--省份shape文件的提取
    简单的EntityFrameWork Code First代码
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9532613.html
Copyright © 2011-2022 走看看