HDU 4494 Teamwork(最大流或最小费用流)
来源:互联网 发布:东研网络 同花顺 编辑:程序博客网 时间:2024/05/22 12:21
题目链接:acm.hdu.edu.cn/showproblem.php?pid=4494
题意:相当于给n个任务,给出每个任务的开始时间和持续时间,每个任务需要不同种类的人来完成,种类之间的人彼此独立不能互换,对于某个任务的人在完成任务后可以赶往其他任务帮忙,问你最少需要多少人才能完成任务
思路:
最大流:这题和最小路径覆盖思想很像,只是每个点覆盖的次数不同了,所以可以拆点构建二分图,如果i能来得及赶上j的任务,那就连一条i到j'的边,流量为i点所拥有的人数,跑出的最大流即是所能节省下的最大人数,总人数相减即可
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <utility>#include <cmath>#include <queue>#include <set>#include <map>#include <climits>#include <functional>#include <deque>#include <ctime>#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int MAXN = 1000;const int MAXM = 50010;const int INF = 0x3f3f3f3f;struct Edge{ int to, next, cap, flow;} edge[MAXM];int tol;int head[MAXN];int gap[MAXN], dep[MAXN], cur[MAXN];void init(){ tol = 0; memset(head, -1, sizeof(head));}void addedge(int u, int v, int w, int rw = 0){ edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++;}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 = edge[i].next) { int v = edge[i].to; 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 > edge[S[i]].cap - edge[S[i]].flow) { Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for (int i = 0; i < top; i++) { edge[S[i]].flow += Min; edge[S[i] ^ 1].flow -= Min; } ans += Min; top = inser; u = edge[S[top] ^ 1].to; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[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 = edge[i].next) if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if (!gap[dep[u]])return ans; dep[u] = Min + 1; gap[dep[u]]++; if (u != start)u = edge[S[--top] ^ 1].to; } return ans;}typedef long long ll;int n, m, g[MAXN][MAXN];ll x[MAXN], y[MAXN], s[MAXN], p[MAXN], t[MAXN];ll v[MAXN][10];ll dist(int i, int j){ return (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);}int solve(int id){ init(); int s = 0, t = 2 * n + 1; for (int i = 1; i <= n; i++) { addedge(s, i, v[i][id]); addedge(i + n, t, v[i][id]); } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if (g[i][j]) addedge(i, j + n, v[i][id]); return sap(s, t, t + 1);}int main(){ int tt; cin >> tt; while (tt--) { ll sum = 0; cin >> n >> m; cin >> x[0] >> y[0]; n--; for (int i = 1; i <= n; i++) { cin >> x[i] >> y[i] >> s[i] >> p[i]; t[i] = s[i] + p[i]; for (int j = 1; j <= m; j++) { cin >> v[i][j]; sum += v[i][j]; } } memset(g, 0, sizeof(g)); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { if (i == j) continue; if (t[i] <= s[j] && dist(i, j) <= (s[j] - t[i]) * (s[j] - t[i])) g[i][j] = 1; } /* for(int i = 1; i <= n; i++) {for(int j = 1; j <= n; j++) printf("%d ", g[i][j]); printf("\n"); }*/ ll ans = 0; for (int i = 1; i <= m; i++) ans += solve(i); cout << sum - ans << endl; } return 0;}
最小费用流:仍是每个点拆成两个,原有的点代表自身任务,然后源点向这些点连一条流量为该点所需人数费用为1的边,这些点再向汇点连边,新拆出的点用来为其他点提供人数,流量为该点人数,费用为0
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <utility>#include <cmath>#include <queue>#include <set>#include <map>#include <climits>#include <functional>#include <deque>#include <ctime>#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int MAXN = 1000;const int MAXM = 50000;const int INF = 0x3f3f3f3f;typedef long long ll;struct Edge{ int to, next, cap, flow, cost;} edge[MAXM];int head[MAXN], tol;int pre[MAXN], dis[MAXN];bool vis[MAXN];int N;//节点总个数,节点编号从0~N-1void init(int n){ N = n; tol = 0; memset(head, -1, sizeof(head));}void addedge(int u, int v, int cap, int cost){ edge[tol].to = v; edge[tol].cap = cap; edge[tol].cost = cost; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = 0; edge[tol].cost = -cost; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++;}bool spfa(int s, int t){ queue<int>q; for (int i = 0; i < N; i++) { dis[i] = INF; vis[i] = false; pre[i] = -1; } dis[s] = 0; vis[s] = true; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost ) { dis[v] = dis[u] + edge[i].cost; pre[v] = i; if (!vis[v]) { vis[v] = true; q.push(v); } } } } if (pre[t] == -1) return false; else return true;}//返回的是最大流,cost存的是最小费用int minCostMaxflow(int s, int t, int &cost){ int flow = 0; cost = 0; while (spfa(s, t)) { int Min = INF; for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) { if (Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow; } for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) { edge[i].flow += Min; edge[i ^ 1].flow -= Min; cost += edge[i].cost * Min; } flow += Min; } return flow;}int n, m, g[MAXN][MAXN];ll x[MAXN], y[MAXN], s[MAXN], p[MAXN], t[MAXN];ll v[MAXN][10];ll dist(int i, int j){ return (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);}int solve(int id){ int s = 0, t = 2 * n + 1; init(t + 1); for (int i = 1; i <= n; i++) { addedge(s, i, v[i][id], 1); addedge(s, i + n, v[i][id], 0); addedge(i, t, v[i][id], 0); } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if (g[i][j]) addedge(i + n, j, v[i][id], 0); // for (int i = 0; i < tol; i++) // printf("%d %d %d\n", edge[i].to, edge[i].cap, edge[i].cost); int cost; minCostMaxflow(s, t, cost); return cost;}int main(){ int tt; cin >> tt; while (tt--) { cin >> n >> m; cin >> x[0] >> y[0]; n--; for (int i = 1; i <= n; i++) { cin >> x[i] >> y[i] >> s[i] >> p[i]; t[i] = s[i] + p[i]; for (int j = 1; j <= m; j++) cin >> v[i][j]; } memset(g, 0, sizeof(g)); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { if(i == j) continue; if (t[i] <= s[j] && dist(i, j) <= (s[j] - t[i]) * (s[j] - t[i])) g[i][j] = 1; } /* for(int i = 1; i <= n; i++) {for(int j = 1; j <= n; j++) printf("%d ", g[i][j]); printf("\n"); }*/ int ans = 0; for (int i = 1; i <= m; i++) ans += solve(i); cout << ans << endl; } return 0;}
0 0
- HDU 4494 Teamwork(最大流或最小费用流)
- HDU 4494 Teamwork 最小费用最大流
- Hdu 4494 Teamwork(最小费用流)
- HDU ACM 4494 Teamwork 最小费用最大流
- hdoj 4494 Teamwork 【最小费用最大流】
- HDU 4494 Teamwork(最大流-Dinic+最小费用最大流-mcmf)
- hdu 4494 Teamwork(多源多汇最小费用最大流,巧妙构图)
- hdu 4494 Teamwork(费用流)
- HDU 4494 - Teamwork(最大流)
- HDU 4494 Teamwork 费用流/网络流
- hdu 4494 Teamwork (可行流的最小流)
- hdu 2686 Matrix - 最小费用最大流 或 多线程DP
- HDU 4494 Teamwork 2013通化邀请赛 B题 费用流
- 费用流+建图——Teamwork ( HDU 4494 )
- hdu 4067(最小费用最大流)
- HDU 1533 (最小费用最大流)(spfa+ek或spfa+dinic)
- 最小费用最大流 HDU 1533
- HDU 1853 最小费用最大流
- 写在前面(一些感想及纪念今天正式开始写博客)
- cell 动画效果之一
- UI基础之----触摸事件
- iOS 支付宝 集成
- Scala入门--集合的使用及对集合操作的函数的使用
- HDU 4494 Teamwork(最大流或最小费用流)
- MonkeyTalk的Pro App Restart、多设备控制、程序控制
- OpenACC2.0标准中文版
- Highcharts实现圆角柱形图
- PropertyPlaceholderConfigurer的用法
- HDU 4248 (DP + 组合数)
- 技术之路
- java注解
- 消除App启动时候的白屏