【最大流 && 点限流】HDU
来源:互联网 发布:合肥数码美工招聘信息 编辑:程序博客网 时间:2024/06/05 11:11
Problem Description
输入T代表有T组测试数据,输入n, d。代表接下来的有两个矩阵n行len列(列是不知道的)。第一个矩阵每个点代表着柱子,对应的值,代表这个柱子的承受能力,青蛙从这里跳走承受能力就会–,直至0就不能承受青蛙了。第二个矩阵L代表青蛙一开始在这里,.代表没有青蛙。问你最少还有多少只青蛙不能跳出边界。每次青蛙能跳的最大距离为d。
思路
核心是能想到最大流,紧接着是建图。拆点限流流量为承受能力,因为点点之间可以到达,所以建图需要注意指向。注意输出样例。was were
#include<bits/stdc++.h>using namespace std;struct node{ int to, cap, next;};#define inf 0x3f3f3f3fnode Map[1000000];int head[1000], vis[1000], cnt;char s[50][50];void add(int u, int v, int w)//前向星存图{ Map[cnt].to = v; Map[cnt].cap = w; Map[cnt].next = head[u]; head[u] = cnt++; Map[cnt].to = u; Map[cnt].cap = 0; Map[cnt].next = head[v]; head[v] = cnt++;}bool bfs(int s, int e){ memset(vis, -1, sizeof(vis)); queue<int> q; q.push(s); vis[s] = 0; while(!q.empty()) { s = q.front(), q.pop(); for(int i = head[s]; ~i; i = Map[i].next) { int to = Map[i].to, cap = Map[i].cap; if(vis[to] == -1 && cap) { vis[to] = vis[s] + 1; q.push(to); } } } if(vis[e] == -1) return 0; else return 1;}int dfs(int s, int e, int f){ if(s == e) return f; int ans = 0; for(int i = head[s]; ~i; i = Map[i].next) { int to = Map[i].to, &cap = Map[i].cap; if(vis[to] > vis[s] && cap) { int d = dfs(to, e, min(f, cap)); if(d) { cap -= d; Map[i^1].cap += d; f -= d; ans += d; if(!f) break; } } } if(ans) return ans; vis[s] = -1; return 0;}int dinic(int s, int e)//求最大流{ int ans = 0; while(bfs(s, e)) { ans += dfs(s, e, inf); } return ans;}double dist(node x, node y)//两点之间的距离{ return sqrt(double((x.to - y.to)*(x.to - y.to) + (x.cap - y.cap)*(x.cap - y.cap)));}int main(){ int T, Case = 1, n, m, d, i, j, len; scanf("%d", &T); while(T--) { scanf("%d %d", &n, &d); memset(head, -1, sizeof(head)); cnt = 0; vector<node> p, ins; for(i = 0; i < n; i++) { scanf("%s", s[i]); len = strlen(s[i]); for(j = 0; j < len; j++) { if(s[i][j] != '0') p.push_back((node){i, j, s[i][j] - '0'});//存起来所有能承受青蛙的柱子 } } for(i = 0; i < n; i++) { scanf("%s", s[i]); for(j = 0; j < len; j++) { if(s[i][j] == 'L') ins.push_back((node){i, j});//存起来所有一开始青蛙的位置 } } int cn = n; n = p.size(); for(i = 0; i < n; i++) { add(i+1, i+n+1, p[i].next);//拆点限流 if((d - p[i].to >= 1) || (d - p[i].cap >= 1) || (len - p[i].cap <= d) || (cn - p[i].to <= d))//能直接跳出去的柱子 { add(i+n+1, 2*n+1, inf); } for(j = i+1; j < n; j++) { double dis = dist(p[i], p[j]); if(dis > d) continue; add(i+n+1, j+1, inf);//点点之间能够到达的建边 并且双向 add(j+n+1, i+1, inf); } } m = ins.size(); for(i = 0; i < m; i++) { for(j = 0; j < n; j++) { if(p[j].to == ins[i].to && p[j].cap == ins[i].cap)//一开始 有青蛙的点 add(0, j+1, 1); } } int ans = dinic(0, 2*n+1);//求最大流,最后注意输出格式 if(ans == m) printf("Case #%d: no lizard was left behind.\n", Case++); else if(ans == m - 1) printf("Case #%d: 1 lizard was left behind.\n", Case++); else printf("Case #%d: %d lizards were left behind.\n", Case++, m - ans); }}
阅读全文
0 0
- 【最大流 && 点限流】HDU
- 【最大流 && 拆点限流】POJ
- HDU 3491 Thieves 【拆点+最大流】
- hdu 4292 拆点 最大流
- HDU 4289 Control(拆点,最大流)
- HDU 4292 Food(拆点,最大流)
- hdu 3277 二分+拆点最大流
- HDU 3036 拆点二分最大流
- HDU 2732 最大流 拆点
- HDU 4289 Control(拆点+最大流)
- hdu 4292(拆点+最大流)
- hdu 4292 Food 最大流+拆点
- HDU 4292 Food 最大流 + 拆点
- HDU 4292--Food【最大流 && 拆点】
- hdu 2732(最大流+拆点)
- 拆点最大流-HDU-4292-Food
- HDU 4292Food(最大流+拆点)
- HDU 2686 Matrix(最大费用最大流+拆点)
- 【Java虚拟机】之五 语法糖的味道
- Java中无参带返回值方法的使用
- 如何才能变得富有?秘密就在这三点里
- Leetcode 661 Image Smoother
- Pop Sequence
- 【最大流 && 点限流】HDU
- Tomcat服务器下载与安装以及在MyEclipse上配置Tomcat服务器
- LeetCode-85-Maximal Rectangle 类似上一题,n遍单调栈
- Etnetera Brevity Challenge
- (51Nod 1183 编辑距离)字符串编辑距离
- 解决springMVC4下使用@ResponseBody的中文乱码问题
- Java 中带参无返回值方法的使用
- 线程间的通信机制
- 原创 蜂蜡等级生产工艺过程