HDU 3549
[problem]
网络流模板
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
#define inf 10000000
const int maxn = 1000;
struct edge{ int to, cap, rev; };
vector<edge> G[maxn];
int level[maxn];
int iter[maxn];
int n, m, Case = 0;
void add_edge(int from, int to, int cap) {
G[from].push_back((edge){to, cap, G[to].size()} );
G[to].push_back((edge){from, 0, G[from].size() - 1});
}
void bfs(int s) {
memset(level, -1, sizeof(level));
queue<int> que;
level[s] = 0;
que.push(s);
while(!que.empty()) {
int v = que.front(); que.pop();
for(int i = 0; i < G[v].size(); i++) {
edge &e = G[v][i];
if (e.cap > 0 && level[e.to] < 0) {
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
}
int dfs(int v, int t, int f) {
if (v == t) return f;
for(int &i = iter[v]; i < G[v].size(); i++) {
edge &e = G[v][i];
if (e.cap > 0 && level[v] < level[e.to]) {
int d = dfs(e.to, t, min(f, e.cap));
if (d > 0) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
int max_flow(int s, int t) {
int flow = 0;
for(;;) {
bfs(s);
if (level[t] < 0) return flow;
memset(iter, 0, sizeof(iter));
int f;
while ((f = dfs(s, t, inf)) > 0) flow += f;
}
}
int main()
{
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) G[i].clear();
for(int i = 1; i <= m; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
add_edge(x, y, z);
}
int ans = max_flow(1, n);
printf("Case %d: %d\n", ++Case, ans);
}
return 0;
}
HDU 3572 Task Schedule
[Problem]
给定n(200)个任务,m个机器,每个任务s[i], t[i], p[i]分别代表最早开始时间,最晚结束时间, 以及需要执行的时间,判断m个机器是否可以完成所有任务。
每个任务可以由不同机器间断性完成
[Solution]
每个任务可以由不同机器间断性完成,所以我们判断该任务在s[i]-t[i]时间内是否承担了P[i]的时间。
每一天抽象为一个点。
每个任务与源点连边,容量为p[i],每个任务与s[i]-t[i]的时间点连边,容量为1, 每个时间点与终点连边,容量为m,最后判断最大流与∑p[i]的关系即可
for(int i = 1; i <= n ;i++) {
int p, s, t;
scanf("%d%d%d", &p, &s, &t);
sum += p;
add_edge(0, days + i, p);
for(int j = s; j <= t; j++) add_edge(days + i, j, 1);
}
for(int i = 1; i <= days; i++) add_edge(i, aim, m);
int ans = max_flow(0, aim);
HDU 3081 Marriage Match II
[Problem]
给定n个女孩和n个男孩的相斥关系,每轮游戏每个女孩选择以前没有选过的一个男孩完成游戏,询问游戏最多可以玩多少轮。
[Solution]
二分 + 网络流
二分游戏进行轮数,问题便成了判断游戏是否可以进行mid轮。
原点与每个女孩连边,容量为mid,终点与男孩连边,容量为mid,不相斥的男孩与女孩连边,容量为1,最后判断最大流是否为mid * n
bool cal(int mid) {
int aim = n * 2 + 1;
for(int i = 0; i <= aim; i++) G[i].clear();
for(int i = 1; i <= n; i++) add_edge(0, i, mid);
for(int i = 1; i <= n; i++) add_edge(i + n, aim, mid);
for(int i = 1; i <= n ;i++) {
int k = find(i);
for(int j = 1; j <= n; j++) if (cnt[k][j] > 0) add_edge(i, j + n, 1);
}
int tot = max_flow(0, aim);
return tot == mid * n;
}
HDU 3277 Marriage Match III
[Problem]
在上一题的基础上,为了让游戏进行更多轮,每个女孩可以选取任意的k个男孩作为自己的companion,询问最大轮数
[Solution]
在上一道题的基础上,每个女孩连接新的节点x,容量为k,x与所有与女孩相斥的男孩相连,容量为1
bool cal(int mid) {
int aim = n * 3 + 1;
for(int i = 0; i <= aim; i++) G[i].clear();
for(int i = 1; i <= n; i++) add_edge(0, i, mid);
for(int i = 1; i <= n; i++) add_edge(i + n, aim, mid);
for(int i = 1; i <= n ;i++) {
int k = find(i);
for(int j = 1; j <= n; j++) if (cnt[k][j] > 0) add_edge(i, j + n, 1);
}
for(int i = 1; i <= n; i++) {
add_edge(i, n * 2 + i, tt);
int k = find(i);
for(int j = 1; j <= n; j++) if (cnt[k][j] == 0) add_edge(n * 2 + i, j + n, 1);
}
int tot = max_flow(0, aim);
return tot == mid * n;
}
HDU 3046 Pleasant sheep and big big wolf
[Problem]
给定矩阵,矩阵元素为1代表是羊,2代表狼,0代表空,在一些位置的边建上fence,使得狼无法到达羊的位置,询问最小fence
[Solution]
原点与羊连边,容量为inf, 终点与狼连边,容量为inf,每个位置与其可以到达的四个位置连边,容量为1,最后跑一边最小割
for(int i = 0; i <= aim; i++) G[i].clear();
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
scanf("%d", &a[i][j]);
if (a[i][j] == 1) add_edge(0, (i - 1) * m + j, inf);
if (a[i][j] == 2) add_edge((i - 1) * m + j, aim, inf);
for(int v = 0; v < 4; v++) {
int x = i + dx[v], y = j + dy[v];
if (x > 0 && x <= n && y > 0 && y <= m) add_edge((i - 1) * m + j, (x - 1) * m + y, 1);
}
}
}
int ans = max_flow(0, aim);
250

被折叠的 条评论
为什么被折叠?



