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

    题目描述

    Link

    有来自 (m) 个不同单位的代表参加一次国际会议。第 (i) 个单位派出了 (r_i) 个代表。

    会议的餐厅共有 (n) 张餐桌,第 (i) 张餐桌可容纳 (c_i) 个代表就餐。

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


    第二道网络流24题 (应该算是比较简单的吧,毕竟自己这种蒟蒻都能想出来),芜湖起飞。

    比较好想的二分图多重匹配问题。

    我们从源点向每个单位连一条容量为 (r_i) 的边,表示这个单位需要在 (r_i) 张不同的桌子就餐。

    在从餐桌向汇点连一条容量为 (c_i) 的边,表示这个餐桌最多能容纳 (c_i) 个人,也就是用来限制最大流的流量。

    剩下的就把每个单位和每个餐桌之间连一条容量为 (1) 边,表示这个单位最多可以派一个人到那个餐桌就餐。

    我们跑出来的最大流就是满足这样就餐的最多的人数。

    无解的情况特判一下就可以。

    输出方案的话就在残留网络中找边权为 (0) 的边输出就行。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int inf = 2147483647;
    const int N = 1010;
    int n,m,s,t,ans,sum,x,tot = 1;
    int head[N],dep[N];
    struct node
    {
    	int to,net,w;
    }e[100010];
    inline int read()
    {
    	int s = 0, w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
    	return s * w;
    }
    void add(int x,int y,int w)
    {
    	e[++tot].w = w;
    	e[tot].to = y;
    	e[tot].net = head[x];
    	head[x] = tot;
    }
    bool bfs()
    {
    	memset(dep,0,sizeof(dep));
    	queue<int> q;
    	q.push(s); dep[s] = 1;
    	while(!q.empty())
    	{
    		int x = q.front(); q.pop();
    		for(int i = head[x]; i; i = e[i].net)
    		{
    			int to = e[i].to;
    			if(e[i].w && !dep[to])
    			{
    				q.push(to);
    				dep[to] = dep[x] + 1;
    				if(to == t) return 1;
    			}
    		}
    	}
    	return 0;
    }
    int dinic(int x,int flow)
    {
    	if(x == t) return flow;
    	int rest = flow;
    	for(int i = head[x]; i; i = e[i].net)
    	{
    		int to = e[i].to;
    		if(e[i].w && dep[to] == dep[x] + 1)
    		{
    			int k = dinic(to,min(e[i].w,rest));
    			if(!k) dep[to] = 0;
    			e[i].w -= k;
    			e[i^1].w += k;
    			rest -= k;
    		}
    	}
    	return flow - rest;
    }
    int main()
    {
    	n = read(); m = read();
    	s = 0; t = n+m+1;
    	for(int i = 1; i <= n; i++)
    	{
    		x = read(); sum += x;
    		add(s,i,x); add(i,s,0);//源点向每个单位连一条边
    	}
    	for(int i = 1; i <= m; i++)
    	{
    		x = read();
    		add(n+i,t,x); add(t,n+i,0);//每个桌子向汇点连边
    	}
    	for(int i = 1; i <= n; i++)
    	{
    		for(int j = 1; j <= m; j++)
    		{
    			add(i,n+j,1); add(n+j,i,0);//单位和餐桌之间互相连边
    		}
    	}
    	int flow = 0;
    	while(bfs())
    	{
    		while(flow = dinic(s,inf)) ans += flow;
    	}
    	if(ans < sum)
    	{
    		printf("%d
    ",0);
    		return 0;
    	}
    	printf("%d
    ",1);
    	for(int i = 1; i <= n; i++)
    	{
    		for(int j = head[i]; j; j = e[j].net)
    		{
    			int to = e[j].to;
    			if(e[j].w == 0) printf("%d ",to-n);
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    一致性哈希算法
    Discourse 的标签(Tag)只能是小写的原因
    JIRA 链接 bitbucket 提示错误 Invalid OAuth credentials
    JIRA 如何连接到云平台的 bitbucket
    Apache Druid 能够支持即席查询
    如何在 Discourse 中配置使用 GitHub 登录和创建用户
    Apache Druid 是什么
    Xshell 如何导入 PuTTYgen 生成的 key
    windows下配置Nginx支持php
    laravel连接数据库提示mysql_connect() :Connection refused...
  • 原文地址:https://www.cnblogs.com/genshy/p/13733606.html
Copyright © 2011-2022 走看看