【HDU】3572 Task Schedule (最大流 ISAP算法)

開始做網絡流了。一開始的學習依然是無腦的,只能借鑑大神的博客。

其實這道題蠻不錯的。說是要對題目進行建模,從而轉化成網絡流的題目。從這道題來看,網絡流看來對思維訓練很有幫助啊。

稍微說一下建模的想法吧。

添加一個超級源點和一個超級匯點。

將每個工程看成一個點。每一天都是一個點。

一個工程對應的每一天都有一個流量爲1,因爲一天只能一個機器去完成一個單元。

每一天到超級匯點流量爲m,因爲有m個機器。

最後判斷,流到超級匯點的流

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 100010
#define MAXM 400040
#define INF 0x7ffffff
int head[MAXN], dep[MAXN], gap[MAXN], cur[MAXN];
int cnt;

struct edge
{
	int v;
	int cap;
	int flow;
	int next;
}edg[MAXM];

struct work
{
	int p, s, e;
}w[MAXN];
void init()
{
	cnt = 0;
	memset(head, -1, sizeof(head));
}

void addedge(int u, int v, int w, int rw = 0)
{
	edg[cnt].v = v;
	edg[cnt].cap = w;
	edg[cnt].flow = 0;
	edg[cnt].next = head[u];
	head[u] = cnt++;
	edg[cnt].v = u;
	edg[cnt].cap = rw;
	edg[cnt].flow = 0;
	edg[cnt].next = head[v];
	head[v] = cnt++;
}
int Q[MAXN];
void BFS(int start, int end)
{
	memset(dep, -1, sizeof(dep));
	memset(gap, 0, sizeof(gap));
	gap[0] = 1;
	int front = 0, rear = 0;
	dep[end] = 0;
	Q[rear++] = end;
	while (front != rear)
	{
		int u = Q[front++];
		for (int i = head[u]; i != -1; i = edg[i].next)
		{
			int v = edg[i].v;
			if (dep[v] != -1)continue;
			Q[rear++] = v;
			dep[v] = dep[u] + 1;
			gap[dep[v]]++;
		}
	}

}

int S[MAXN];
int sap(int start, int end, int n)
{
	BFS(start, end);
	memcpy(cur, head, sizeof(head));
	int top = 0;
	int u = start;
	int ans = 0;
	while (dep[start] < n)
	{
		if (u == end)
		{
			int Min = INF;
			int inser;
			for (int i = 0; i < top;i++)
			if (Min>edg[S[i]].cap - edg[S[i]].flow)
			{
				Min = edg[S[i]].cap - edg[S[i]].flow;
				inser = i;
			}
			for (int i = 0; i < top; i++)
			{
				edg[S[i]].flow += Min;
				edg[S[i] ^ 1].flow -= Min;
			}
			ans += Min;
			top = inser;
			u = edg[S[top] ^ 1].v;
			continue;
		}
		bool flag = false;
		int v;
		for (int i = cur[u]; i != -1; i = edg[i].next)
		{
			v = edg[i].v;
			if (edg[i].cap - edg[i].flow&&dep[v] + 1 == dep[u])
			{
				flag = true;
				cur[u] = i;
				break;
			}
		}
		if (flag)
		{
			S[top++] = cur[u];
			u = v;
			continue;
		}
		int Min = n;
		for (int i = head[u]; i != -1; i = edg[i].next)
			if (edg[i].cap - edg[i].flow&&dep[edg[i].v] < Min)
			{
				Min = dep[edg[i].v];
				cur[u] = i;
			}
			gap[dep[u]]--;
			if (!gap[dep[u]])return ans;
			dep[u] = Min + 1;
			gap[dep[u]]++;
			if (u != start)u = edg[S[--top] ^ 1].v;
	}
	return ans;
}

int main()
{
	int t;
	cin >> t;
	int icase = 1;
	int n, m;
	while (t--)
	{
		init();
		scanf("%d%d", &n, &m);
		int E=0;
		int res = 0;
		for (int i = 1; i <=n; i++)
		{
			scanf("%d%d%d", &w[i].p, &w[i].s, &w[i].e);
			addedge(0, i, w[i].p);
			E = max(E, w[i].e);
			res += w[i].p;
			for (int j = w[i].s; j <= w[i].e; j++)
				addedge(i, n + j, 1);
		}
		for (int i = 1; i <= E; i++)
		{
			addedge(n + i, n + E + 1, m);
		}
		printf("Case %d: ", icase++);
		if (res == sap(0, n + E + 1, n + E + 2))
			puts("Yes");
		else
			puts("No");
		puts("");
	}
}

量是否等於總的就可以了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章