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

    题目:洛谷P3254。

    题目大意:
    有n个单位和m张桌子,每个单位有一定的人数,每张桌子也有一定的容量。一张桌子上不能有两个同一单位的人。现在问你能否坐下,若能则输出一种方案。
    解题思路:
    最大流。
    从S向每个单位连一条容量为(单位人数)的边,代表这个单位有那么多人。
    从每张桌子向T连一条容量为(桌子容量)的边,代表这张桌子能做那么多人。
    从每个单位向每张桌子连一条容量为1的边,代表每个单位在一张桌子上只能坐一个人。
    然后若最大流量不等于总人数,则无解。否则有解。
    输出方案,就枚举边,对于一条从单位流向桌子的边,若跑完剩余容量为0,则该单位在这张桌子上坐了人。

    C++ Code:

    #include<bits/stdc++.h>
    #define S 0
    #define T 1000
    struct edge{
    	int from,to,cap,nxt;
    }e[200000];
    inline int readint(){
    	int c=getchar(),d=0;
    	for(;!isdigit(c);c=getchar());
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    	return d;
    }
    int cnt=1,n,m,head[1005],s=0,level[1005],iter[1005];
    std::vector<int>v[300]; 
    inline int addedge(const int u,const int v,const int t){
    	e[++cnt]=(edge){u,v,t,head[u]};
    	head[u]=cnt;
    	e[++cnt]=(edge){v,u,0,head[v]};
    	head[v]=cnt;
    }
    std::queue<int>q;
    inline int min(const int a,const int b){return a<b?a:b;}
    void bfs(){
    	q.push(S);
    	level[S]=1;
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int i=head[u];~i;i=e[i].nxt)
    		if(e[i].cap&&!~level[e[i].to]){
    			level[e[i].to]=level[u]+1;
    			q.push(e[i].to);
    		}
    	}
    }
    int dfs(const int u,const int f){
    	if(!f||u==T)return f;
    	for(int& i=iter[u];~i;i=e[i].nxt)
    	if(e[i].cap&&level[e[i].to]>level[u]){
    		int d=dfs(e[i].to,min(f,e[i].cap));
    		if(d){
    			e[i].cap-=d;
    			e[i^1].cap+=d;
    			return d;
    		}
    	}
    	return 0;
    }
    int dinic(){
    	for(int flow=0,f;;){
    		memset(level,-1,sizeof level);
    		if(bfs(),!~level[T])return flow;
    		memcpy(iter,head,sizeof head);
    		while(f=dfs(S,0x3f3f3f3f))flow+=f;
    	}
    }
    int main(){
    	memset(head,-1,sizeof head);
    	n=readint(),m=readint();
    	for(int i=1;i<=n;++i){
    		int p=readint();
    		s+=p;
    		addedge(S,i,p);
    	}
    	for(int i=1;i<=m;++i)addedge(n+i,T,readint());
    	for(int i=1;i<=n;++i)
    	for(int j=1;j<=m;++j)
    	addedge(i,n+j,1);
    	if(dinic()!=s)return puts("0"),0;
    	puts("1");
    	for(int i=1;i<=cnt;++i)
    	if(e[i].from<=n&&e[i].from&&e[i].to>n&&e[i].to<=n+m&&!e[i].cap)v[e[i].from].push_back(e[i].to-n);
    	for(int i=1;i<=n;++i)
    	if(v[i].size()){
    		for(int j=v[i].size()-1;j>0;--j)printf("%d ",v[i][j]);
    		printf("%d
    ",v[i][0]);
    	}else putchar('
    ');
    	return 0;
    }
    
  • 相关阅读:
    Linux常用命令及示例(全)
    linux下安装配置svn服务器
    Kafka、Redis和其它消息组件比较
    ORACLE定时备份方案
    mysql库表优化实例
    携程apollp快速部署DVE集群
    windows 安装Zookeeper 配置集群
    Ubuntu 18.04 LTS 修改Host,使用Host访问
    PowerShell因为在此系统中禁止执行脚本......
    常用第三方工具的Docker命令
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9130089.html
Copyright © 2011-2022 走看看