hdu 2732 网络流,建图
2017-10-02 11:10
239 查看
题目大意:
给了n和d,表示有n行的图,(列数没给),对于每一个人都可以最长跳d的距离,对于每一个柱子有一个限定条件,只能从这里跳出去多少次。给了两张图,一张表示柱子的限定条件,一张给了现在那些柱子上有人。问有几个人不能跳到图的外面。
思路:
最大流建图。将图的外面抽象为一个汇点t,对于图中本来就可以跳出去的点,就可以连一条边到t了。对于可以跳到图中别的点的,就可以从这个点连一条边过去。比较直观的想法就是这些边的容量都设为这个柱子限定的次数,最后跑最大流就好了。但是如果这个柱子可以跳到旁边很多的点上,每一个边的容量都是这个限定次数的话,等于限定的次数被放大了。那么就考虑拆点,将每个点拆成点1,点2,1->2连一条边容量为限定的次数。对于能跳到别的边,就从2连一条边到外面的点,容量为INF。
步骤:
拆点
1.将能够直接跳出去的点,拆出的第一个点连到t,容量为限定的次数。
2.不能直接跳出去的,将点1连到点2,容量为限定的次数。
3.对于能跳到别的点的,将这个点2连到别的点的点1,容量为INF。
4.对于柱子上有人的,从s连一条边到该点的点1,容量为1。
跑最大流。
题解转自:http://blog.csdn.net/liujc_/article/details/51179046
代码:
给了n和d,表示有n行的图,(列数没给),对于每一个人都可以最长跳d的距离,对于每一个柱子有一个限定条件,只能从这里跳出去多少次。给了两张图,一张表示柱子的限定条件,一张给了现在那些柱子上有人。问有几个人不能跳到图的外面。
思路:
最大流建图。将图的外面抽象为一个汇点t,对于图中本来就可以跳出去的点,就可以连一条边到t了。对于可以跳到图中别的点的,就可以从这个点连一条边过去。比较直观的想法就是这些边的容量都设为这个柱子限定的次数,最后跑最大流就好了。但是如果这个柱子可以跳到旁边很多的点上,每一个边的容量都是这个限定次数的话,等于限定的次数被放大了。那么就考虑拆点,将每个点拆成点1,点2,1->2连一条边容量为限定的次数。对于能跳到别的边,就从2连一条边到外面的点,容量为INF。
步骤:
拆点
1.将能够直接跳出去的点,拆出的第一个点连到t,容量为限定的次数。
2.不能直接跳出去的,将点1连到点2,容量为限定的次数。
3.对于能跳到别的点的,将这个点2连到别的点的点1,容量为INF。
4.对于柱子上有人的,从s连一条边到该点的点1,容量为1。
跑最大流。
题解转自:http://blog.csdn.net/liujc_/article/details/51179046
代码:
#include <bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 808; const int Mod = 1e9 + 7; #define ll long long #define mem(x,y) memset(x,y,sizeof(x)) #define IO ios_base::sync_with_stdio(0), cin.tie(0); inline ll gcd(ll a, ll b) {return a % b == 0 ? b : gcd(b, a % b);} inline ll lcm(ll a, ll b) {return a / gcd(a, b) * b;} inline ll quick_pow(ll x, int k) {ll ans = 1; while (k) { if (k & 1) ans = (ans * x) % Mod; x = x * x % Mod; k >>= 1; } return ans;} int dep[maxn]; struct Node { int v, w, re_id; Node() {}; Node(int a, int b, int c) { v = a, w = b, re_id = c; } }; vector<Node> node[maxn]; void addEdge(int u, int v, int w) { node[u].push_back(Node(v, w, node[v].size())); node[v].push_back(Node(u, 0, node[u].size() - 1)); } int bfs(int s, int t) { queue<int> Q; mem(dep, -1); dep[s] = 0; Q.push(s); while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = 0; i < node[u].size(); i++) { int v = node[u][i].v; if (node[u][i].w > 0 && dep[v] == -1) { dep[v] = dep[u] + 1; Q.push(v); } } } return dep[t] != -1; } int dfs(int s, int t, int f) { if (s == t || f == 0) return f; int sumf = 0; for (int i = 0; i < node[s].size(); i++) { int v = node[s][i].v; if (node[s][i].w > 0 && dep[v] == dep[s] + 1) { int tmp = dfs(v, t, min(f, node[s][i].w)); if (tmp > 0) { node[s][i].w -= tmp; node[v][node[s][i].re_id].w += tmp; sumf += tmp, f -= tmp; } } } if (sumf == 0) dep[s] = -1; return sumf; } int dinic(int s, int t) { int ans = 0; while (bfs(s, t)) ans += dfs(s, t, INF); return ans; } char s1[30][30], s2[30][30]; int xx[4] = {1, -1, 0, 0}, yy[4] = {0, 0, 1, -1}, line, len, d; bool canJumpAway(int x, int y) { for (int i = 1; i <= 4; i++) { int a = x + xx[i - 1] * d, b = y + yy[i - 1] * d; if (a <= 0 || a > line || b <= 0 || b > len) return 1; } return 0; } int main() { int tt, icase = 1, s = 0, t = 801; cin >> tt; while (tt--) { for (int i = 0; i < maxn; i++)node[i].clear(); cin >> line >> d; for (int i = 1; i <= line; i++)scanf("%s", s1[i]); for (int i = 1; i <= line; i++) scanf("%s", s2[i]); len = strlen(s1[1]); int sum = 0; for (int i = 1; i <= line; i++) { for (int j = 0; j < len; j++) { int x = i, y = j + 1; int a1 = (x - 1) * len + y, a2 = a1 + 400; if (s2[i][j] == 'L') { // 对于柱子上有人的,从s连一条边到该点的点1,容量为1 sum++; addEdge(s, a1, 1); } if (s1[i][j] == '0') continue; if (canJumpAway(x, y))addEdge(a1, t, s1[i][j] - '0');//将能够直接跳出去的点,拆出的第一个点连到t,容量为限定的次数 else { addEdge(a1, a2, s1[i][j] - '0'); // 不能直接跳出去的,将点1连到点2,容量为限定的次数。 for (int k = -d; k <= d; k++) for (int q = -d; q <= d; q++) { if (k == 0 && q == 0) continue; int a = x + k, b = y + q; if (k * k + q * q <= d * d && s1[a][b - 1] != '0') addEdge(a2, (a - 1)*len + b, INF); // 对于能跳到别的点的,将这个点2连到别的点的点1,容量为INF } } } } int ans = sum - dinic(s, t); if (ans == 0) printf("Case #%d: no lizard was left behind.\n", icase++); else if (ans == 1) printf("Case #%d: 1 lizard was left behind.\n", icase++); else printf("Case #%d: %d lizards were left behind.\n", icase++, ans); } }
相关文章推荐
- HDU--杭电--2732//POJ--2711--Leapin' Lizards--网络流
- HDU 4888 Redraw Beautiful Drawings 网络流 建图
- hdu 2732 Leapin' Lizards 网络流 拆点构图
- 【HDU - 3277】Marriage Match III 【网络流经典建图+拆点+二分+并查集or floyd】
- HDU-2732 (Leapin' Lizards) 网络流
- hdu 2732 Leapin' Lizards 【图论-网络流-最大流】
- POJ 2711 Leapin' Lizards / HDU 2732 Leapin' Lizards / BZOJ 1066 [SCOI2007]蜥蜴(网络流,最大流)
- hdu 2732(网络流)
- hdu 2732(网络流)
- HDU 4888 Redraw Beautiful Drawings 网络流 建图
- HDU 3657 Game 网络流--最大独立集
- HDU 4494 Teamwork 费用流/网络流
- hdu 4975 A simple Gaussian elimination problem.(网络流,推断矩阵是否存在)
- 【网络流第二步】Hdu 1532——Drainage Ditches 邻接矩阵版
- hdu 3549 最大网络流 Flow Problem
- hdu 3998 Sequence 网络流
- hdu1532网络流
- poj 1149 PIGS【网络流经典建图】
- HDU 2853 Assignment 最大匹配+求最少改动的匹配数 之神奇建图
- 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)