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

    题目大意:

    (m)个单位,每个单位有(r_i)个人

    共有(n)个桌子,每张桌子可以容纳(c_i)个人

    现在要求每个单位每张桌子只能做一个人,求满足要求的方案

    (mle 150,nle 270)

    二分图多重匹配,这里采用网络流解法

    单位作为二分图的左部,桌子作为二分图右部

    由于每个单位每张桌子只能坐一个人,所以每个单位向每个桌子连一条容量为(1)的边。

    源点向每个单位连容量为(r_i)的边,每张桌子向汇点连容量为(c_i)的边,跑一下最大流,看看最大流是否等于(sumlimits_{i=1}^{m}r_i)

    统计答案直接枚举

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
    	int x=0,f=1;
    	char ch;
    	for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    	if(ch=='-') f=0,ch=getchar();
    	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	return f?x:-x;
    }
    const int inf=0x7f7f7f7f;
    int n,m,st,ed,ret,sum;
    int head[10010],cur[10010],d[10010],cnt=1;
    struct node
    {
    	int nxt,to,val;
    }a[100010];
    inline void add(int x,int y,int z)
    {
    	a[++cnt].nxt=head[x];
    	a[cnt].to=y;
    	a[cnt].val=z;
    	head[x]=cnt;
    }
    queue<int> q;
    inline bool bfs()
    {
    	for(int i=1;i<=n+m+2;++i)
    	{
    		cur[i]=head[i];
    		d[i]=0;
    	}
    	q.push(st);d[st]=1;
    	while(!q.empty())
    	{
    		int now=q.front();
    		q.pop();
    		for(int i=head[now];i;i=a[i].nxt)
    		{
    			int t=a[i].to;
    			if(!d[t]&&a[i].val)
    			{
    				d[t]=d[now]+1;
    				q.push(t);
    			}
    		}
    	}
    	return d[ed];
    }
    inline int dfs(int now,int c)
    {
    	if(now==ed||!c) return c;
    	int ret=c,f;
    	for(int i=cur[now];i;i=a[i].nxt)
    	{
    		cur[now]=i;
    		int t=a[i].to;
    		if(d[t]==d[now]+1)
    		{
    			f=dfs(t,min(a[i].val,ret));
    			if(!f) continue;
    			a[i].val-=f;
    			a[i^1].val+=f;
    			ret-=f;
    			if(!ret) return c;
    		}
    	}
    	if(c==ret) d[now]=0;
    	return c-ret;
    }
    inline void dinic()
    {
    	while(bfs()) ret+=dfs(st,inf);
    	if(ret!=sum)//最大流是否等于人数
    	{
    		puts("0");
    		return;
    	}
    	puts("1");
    	for(int x=1;x<=m;++x)
    	{
    		for(int i=head[x];i;i=a[i].nxt)
    		{
    			int t=a[i].to;
    			if(t<=m||t>n+m||a[i].val) continue;
    			printf("%d ",t-m);
    		}
    		putchar('
    ');
    	}
    }
    signed main()
    {
    	m=read(),n=read();
    	st=n+m+1,ed=n+m+2;
    	for(int x,i=1;i<=m;++i)//每个单位和源点连边,边权为人数
    	{
    		x=read();
    		add(st,i,x);
    		add(i,st,0);
    		sum+=x;
    	} 
    	for(int x,i=1;i<=n;++i)//每张桌子和汇点连边,边权为容量
    	{
    		x=read();
    		add(i+m,ed,x);
    		add(ed,i+m,0);
    		for(int j=1;j<=m;++j)//单位和桌子连边,边权为1限制人数
    		{
    			add(j,i+m,1);
    			add(i+m,j,0);
    		}
    	}
    	dinic();
    return 0;
    }
    
  • 相关阅读:
    OC文件操作、获取文件属性
    【解决方法】Unexpected namespace prefix “xmlns” found for tag Layout
    hdu5301(2015多校2)--Buildings(构造)
    java_GC
    iOS开发项目之四 [ 调整自定义tabbar的位置与加号按钮的位置]
    李洪强-C语言3-数组
    李洪强-C语言2-字符串
    李洪强-C语言1-指针
    【C语言】07-基本语句和运算
    【C语言】06-基本数据类型
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12095034.html
Copyright © 2011-2022 走看看