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

来源:互联网 发布:音视频编辑软件 编辑:程序博客网 时间:2024/05/16 14:26

开始做网络流了。一开始的学习依然是无脑的,只能借鉴大神的博客。

其实这道题蛮不错的。说是要对题目进行建模,从而转化成网络流的题目。从这道题来看,网络流看来对思维训练很有帮助啊。

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

添加一个超级源点和一个超级汇点。

将每个工程看成一个点。每一天都是一个点。

一个工程对应的每一天都有一个流量为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 0x7ffffffint 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");elseputs("No");puts("");}}

量是否等于总的就可以了。

0 0
原创粉丝点击