• 周六. 10月 8th, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

洛谷 P3254 圆桌问题

admin

11月 28, 2021

题目传送门

源点到i单位的连容量为(r_i)的边,单位到每个餐桌连容量为1的边,餐桌j到汇点连容量为(c_j)的边,跑最大流

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define pd(i) (i % 2 == 1) ? i + 1 : i - 1

using namespace std;

int m,n,r,c,s,t,tot,dis[500],num,hu[500],ans;
vector<int> d[500];
struct kkk {
	int fr,to,ll,rl;
}e[200001];

inline void add(int x,int y,int v) {
	e[++tot].fr = x;
	e[tot].to = y;
	e[tot].rl = v;
	e[tot].ll = 0;
	d[x].push_back(tot);
	e[++tot].fr = y;
	e[tot].to = x;
	e[tot].ll = 0;
	e[tot].rl = 0;
	d[y].push_back(tot);
}

inline bool bfs() {
	memset(dis,-1,sizeof(dis));
	queue<int> q;
	q.push(s);
	dis[s] = 0;
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		for(int i = 0;i < d[u].size(); i++) {
			kkk o = e[d[u][i]];
			if(dis[o.to] == -1 && o.rl > o.ll) {
				dis[o.to] = dis[u] + 1;
				q.push(o.to);
			}
		}
	}
	return dis[t] != -1;
}

inline int dfs(int u,int a) {
	if(u == t || a == 0) return a;
	int sum = 0;
	for(int &i = hu[u];i < d[u].size(); i++) {
		kkk &o = e[d[u][i]];
		if(dis[o.to] == dis[u] + 1) {
			int f = dfs(o.to,min(a,o.rl - o.ll));
			o.ll += f;
			e[pd(d[u][i])].ll -= f;
			a -= f;
			sum += f;
			if(a == 0) break;
		}
	}
	return sum;
}

int main() {
	scanf("%d%d",&m,&n);
	t = m + 1 + n;
	for(int i = 1;i <= m; i++) {
		scanf("%d",&r);
		num += r;
		add(s,i,r);
	}
	for(int i = 1;i <= n; i++) {
		scanf("%d",&c);
		add(i + m,t,c);
	}
	for(int i = 1;i <= m; i++)
		for(int j = 1;j <= n; j++)
			add(i,j + m,1);
	while(bfs()) {
		memset(hu,0,sizeof(hu));
		ans += dfs(s,10000000);
	}
	if(ans == num) printf("1
");
	else {printf("0
"); return 0;}
	for(int i = 1;i <= m; i++) {
		for(int j = 0;j < d[i].size(); j++)
			if(e[d[i][j]].ll == 1 && e[d[i][j]].to != 0)
				printf("%d ",e[d[i][j]].to - m);
		printf("
");
	}
	return 0;
}

发表回复

您的电子邮箱地址不会被公开。