Conveyor belts---流+分点建图

本文介绍了一种解决工厂生产调度问题的算法,通过将生产结点和时间状态转换为图论问题,利用最大流算法确定最优的生产者运行方案,确保在不违反生产约束条件下达到最大的生产效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Conveyor belts
Your factory has N junctions (numbered from 1 to N) connected by M conveyor belts. Each conveyor belt transports any product automatically from one junction to another junction in exactly one minute. Note that each conveyor belt only works in one direction. There can be more than one conveyor belt connecting two junctions, and there can be a conveyor belt connecting a junction to itself.

There are K producers (machines which produce the products) located at the first K junctions, i.e. junctions 1,2,…,K. The producer at junction j produces an product each minute (x⋅K+j) for all integers x≥0 and j=1,2,…,K. All products are transported immediately via the conveyor belts to the warehouse at junction N, except for those produced at junction N (if any). Items produced at junction N are directly delivered to the warehouse (there is no need to use the conveyor belts).

At each junction, there is a robot deciding which conveyor belts the incoming product should go to in a negligible time (instantly). The robots can be programmed such that all products produced by a producer are always delivered to the warehouse via the same route. Once the robots are programmed, the routing can no longer be changed. Items from different producers may have the same or different routes.

A prudent potential investor comes and wants to inspect the factory before making any decision. You want to show to the potential investor that your factory employs a good risk management policy. Thus, you want to make sure that each conveyor belt only transports at most one product at any time; i.e. two products cannot be on the same conveyor belt at the same time. On the other hand, there is no limit on the number of products at the junctions (the robots have a lot of arms!). To achieve this, you may turn off zero or more producers, but you still want to maximize the production, hence, this problem.

Find the maximum number of producers that can be left running such that all the produced products can be delivered to the warehouse and each conveyor belt transports at most 1 product at any time.

Input
The first line contains three integers N, K, and M (1≤K≤N≤300; 0≤M≤1000) representing the number of junctions, the number of producers, and the number of conveyor belts, respectively.

The next M lines, each contains two integers a and b (1≤a,b≤N) representing a conveyor belt connecting junction a and junction b with the direction from a to b.

Output
The output contains an integer denoting the maximum number of producers which can be left running such that all the produced products can be delivered to the warehouse and each conveyor belt transports at most one product at any time.

Explanation
In Sample Input 1, N=4, K=2, M=3, and the directed edges are {(1,3), (2,3), (3,4)}. There is only one possible delivery route for each producer, i.e. 1→3→4 for producer 1, and 2→3→4 for producer 2. Both producers are using conveyor belt (3,4), however, the products from producer 1 are on the conveyor belt (3,4) on minutes 2,4,6,… (even minutes), while the products from producer 2 are on the conveyor belt (3,4) on minutes 3,5,7,… (odd minutes). Therefore, both producers can be left running.

In Sample Input 2, N=5, K=2, M=4, and the directed edges are {(1,3), (3,4), (2,4), (4,5)}. Similar to the previous example, there is only one possible delivery route for each product produced by each producer. In this example, only one producer can be left running as products from both producers (1 and 2) are on the conveyor belt (4,5) at the same time if both are running.

vj题目

题解:
此题难点在建图。
每个生产结点只在特定且连续的时间生产,即周期为K
而产品在传送带上传递需要1时间,每个结点分裂成的K个点就对应每个结点在周期内每个时间内的状态,而每个结点的此状态连接下一个结点的下一状态。
求可同时存在的状态最大数量(小于等于K)
即最大流。

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define me(x,y) memset(x,y,sizeof(x))
typedef int ll;
using namespace std;
const int N = 307, M = 1007;
int n, m, K, head[N * N], cnt = 1, f, t, d[N * N];//这个计数器cnt要赋值为1,
int mark[N];
ll x, ans, ca;

struct edge {
	int to = 0, nxt = 0;
	ll cap = 0;
}e[M * M];

inline void add_(int f, int t, ll c) {
	cnt++;
	e[cnt].to = t;
	e[cnt].cap = c;
	e[cnt].nxt = head[f];
	head[f] = cnt;
}
//循环键点,每个点分成K个
inline void add_c(int f, int t) {
	add_(f * K + 1, (t - 1) * K + 2, 1);
	add_((t - 1) * K + 2, f * K + 1, 0);
	for (int i = 1; i < K; i++) {
		add_((f - 1) * K + 1 + i, (t - 1) * K + 2 + i, 1);
		add_((t - 1) * K + 2 + i, (f - 1) * K + 1 + i, 0);
	}
}
bool bfs() {//bfs部分,寻找最短路径
	queue<int>q;
	me(d, 0);//清空路径距离
	q.push(1); d[1] = 1;
	while (!q.empty()) {
		int u = q.front(); q.pop();
		for (int i = head[u], v; i; i = e[i].nxt)
			if (!d[v = e[i].to] && e[i].cap) {//当最短路径的容量填满时,删除次边
				q.push(v); d[v] = d[u] + 1;
				if (v <= n * K +1&& v >= (n - 1) * K + 2) return 1;//中断,表示路径存在,还有增广路径
			}
	}
	return 0;
}

ll dfs(int u, ll flow) {//dfs部分,填增广路径的流
	if (u <= n * K+1 && u >= (n - 1) * K + 2) return flow;
	ll rest = flow;//路径余下的容量
	for (int i = head[u], v; i && rest; i = e[i].nxt) {
		if (e[i].cap && d[v = e[i].to] == d[u] + 1) {//只搜索之前bfs标记的增广路径
			ll tmp = dfs(v, min(rest, e[i].cap));//搜索此路径最大径流
			if (!tmp) d[v] = 0;//若容量满,则“删除”此点
			rest -= tmp; e[i].cap -= tmp; e[i ^ 1].cap += tmp;//更新正向路径的容量(减少),反向路径的容量(增加)
		}
	}
	return flow - rest; //真正给出去的 ,若为汇,则返回0
}

int main() {
	cin >> n >> K >> m;
	//每个点分成K个,即K*n个点,注意源点的建立
	for (int i = 1; i <= K; i++) {
		add_(1, (i - 1) * K + i+1, 1);
		add_((i - 1) * K + i + 1, 1, 0);
	}
	for (int i = 0; i < m; i++) {
		cin >> f >> t;
		add_c(f, t);
	}
	int tmp = 0;
	while (bfs())while (tmp = dfs(1, N))ans += tmp;
	cout << ans << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值