kebab HDU - 2883(思维建图,最大流)

参考文章

题目链接(戳这)

思路:
一道比较好的最大流题目,与常规方法:将点划分每个单位时间点所对应的状态点有所不同,这里采用了时间段的思想,记录所有客人需求的时间点,进行去重,这样就有了一个个时间段
这里利用时间段的思想,避免了高达1e6的时间范围下的按单位时间的复杂建图情况,并且考虑到可以将每个顾客的需求量拆分成单位长度,因此可以直接将超级源点与人之间的容量设置为总烧烤时间


建图模式:
超级源点->人->时间段->超级汇点
超级源点->人:总烧烤时间 人->时间段:INF
时间段->超级汇点:时间长度*机器数


代码如下:

#pragma GCC optimize(2)
#include<cstdio>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<list>
#include<map>
#include<set>
#include<cmath>
#include<cstring>
#include<iostream>
#define _PI acos(-1.0)
#define esp 1e-9
#define IOS ios::sync_with_stdio(0);cin.tie(0);
#define FRE freopen("abc.in", "r", stdin)
#define mEm(X,Y) memset(X,Y,sizeof(X))
#define pb(a) push_back(a)
#define pa(a) pop_back(a)
#define rep(i,a,b) for(int i=a;i<b;++i)
#define rep1(i,a,b) for(int i=a;i<=b;++i)
#define INF 0x3f3f3f3f
typedef long long LL;
typedef unsigned long long ULL;
LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; }
void exgcd(LL a, LL b, LL& x, LL& y) {
	if (!b) {
		x = 1, y = 0;
		return;
	}
	exgcd(a, b, y, x);
	y -= a / b * x;
}
using namespace std;
/*===========================================*/
//使用非vector链式前向星 
class MAXFLOW
{
public:
	static const int MAXN = 100200;

	struct Edge
	{
		int v, flow, next;
	} e[MAXN << 2];

	int head[MAXN], edge_num, layer[MAXN], start, end;

	void reload()
	{
		edge_num = 0;
		memset(head, -1, sizeof(head));
	}

	void addedge(int u, int v, int w)
	{
		e[edge_num].v = v;
		e[edge_num].flow = w;
		e[edge_num].next = head[u];
		head[u] = edge_num++;
		e[edge_num].v = u;
		e[edge_num].flow = 0;
		e[edge_num].next = head[v];
		head[v] = edge_num++;
	}

	bool bfs()
	{
		queue<int> Q;
		Q.push(start);
		memset(layer, 0, sizeof(layer));
		layer[start] = 1;
		while (Q.size())
		{
			int u = Q.front();
			Q.pop();

			if (u == end)
				return true;

			for (int j = head[u]; j != -1; j = e[j].next)
			{
				int v = e[j].v;
				if (layer[v] == false && e[j].flow)
				{
					layer[v] = layer[u] + 1;
					Q.push(v);
				}
			}
		}

		return false;
	}
	int dfs(int u, int MaxFlow, int End)
	{
		if (u == End)
			return MaxFlow;

		int uflow = 0;

		for (int j = head[u]; j != -1; j = e[j].next)
		{
			int v = e[j].v;

			if (layer[v] - 1 == layer[u] && e[j].flow)
			{
				int flow = min(MaxFlow - uflow, e[j].flow);
				flow = dfs(v, flow, End);
				e[j].flow -= flow;
				e[j ^ 1].flow += flow;

				uflow += flow;

				if (uflow == MaxFlow)
					break;
			}
		}
		if (uflow == 0)
			layer[u] = 0;
		return uflow;
	}
	int dinic()
	{
		int MaxFlow = 0;

		while (bfs())
			MaxFlow += dfs(start, 0x3f3f3f3f, end);
		return MaxFlow;
	}
}sol;

vector<int> s, e;
vector<int> time;

int main()
{
	int n, m;
	while (~scanf("%d%d", &n, &m))
	{
		time.clear(), s.clear(), e.clear();
		int a, b, c, d;
		sol.reload();
		int tot = 0;
		rep1(i, 1, n)
		{
			scanf("%d%d%d%d", &a, &b, &c, &d);
			s.push_back(a), e.push_back(c), time.push_back(a), time.push_back(c);
			sol.addedge(0, i, b * d);
			tot += b * d;
		}
		sort(time.begin(), time.end());
		time.erase(unique(time.begin(), time.end()), time.end());
		sol.start = 0, sol.end = n + time.size();
		rep(i, 1, time.size())
		{
			sol.addedge(n + i, sol.end, m * (time[i] - time[i - 1]));
			rep(j, 0, n)
			{
				if (time[i - 1] >= s[j] && time[i] <= e[j])
					sol.addedge(j + 1, n + i, INF);
			}
		}
		printf("%s\n", sol.dinic() == tot ? "Yes" : "No");
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值