kebab HDU - 2883(思維建圖,最大流)

Dream~wings發表於2020-10-23

參考文章

題目連結(戳這)

思路:
一道比較好的最大流題目,與常規方法:將點劃分每個單位時間點所對應的狀態點有所不同,這裡採用了時間段的思想,記錄所有客人需求的時間點,進行去重,這樣就有了一個個時間段
這裡利用時間段的思想,避免了高達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");
	}
}

相關文章