HDU 3491 Thieves(经典拆点建图,割点)
来源:互联网 发布:条形码 连接数据库 编辑:程序博客网 时间:2024/05/21 03:55
题目地址
题意:有一群小偷要从s点逃到t点,告诉你这个城市的道路图,并且告诉你每个关键点要多少警察才不会让小偷逃走,问你最少要多少警察才能阻止小偷逃走(小偷会知道警察的布局)
思路:明显的最小割点的题目,解决这类割点问题一般都是进行拆点建图,把每个点拆成两个点(i,i+n)和一条容量为代价的边,然后道路的起点就是该起点的出点(x+n),终点就是该终点的入点(y),容量为inf无限大,这样就不会去割边了,最后以为最小割等于最大流,所以跑一边最大流就好了。
#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 40010#define M 100010 #define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1000000007;int head[N], level[N];int n, m, cnt;struct node { int to; int cap;//剩余流量 int next;}edge[2 * M];struct Dinic { void init() { memset(head, -1, sizeof(head)); cnt = 0; } void add(int u, int v, int cap) {//有向图 edge[cnt].to = v, edge[cnt].cap = cap, edge[cnt].next = head[u], head[u] = cnt++; edge[cnt].to = u, edge[cnt].cap = 0, edge[cnt].next = head[v], head[v] = cnt++;//反向边 } bool bfs(int s, int t) {//建立分层图 memset(level, -1, sizeof(level)); queue<int>q; level[s] = 0;//源点的层次最高 q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (edge[i].cap > 0 && level[v] < 0) { level[v] = level[u] + 1; q.push(v); } } } return level[t] != -1; } int dfs(int u, int t, int num) {//找增广路 if (u == t) {//找到了汇点返回当前的最小值,在这条路径上分别减去最小值 return num; } for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (edge[i].cap > 0 && level[u] < level[v]) { int d = dfs(v, t, min(num, edge[i].cap)); if (d > 0) { edge[i].cap -= d; edge[i ^ 1].cap += d;//反向边加值 return d; } } } level[u] = -1; return 0; } int minflow(int s, int t) {//源点和汇点 int sum = 0, num; while (bfs(s, t)) { while (num = dfs(s, t, inf), num > 0) {//当前层次图不断的找增广路 sum += num; } } return sum; }}dc;int main() { cin.sync_with_stdio(false); int T; int a, b; int s, t; cin >> T; while (T--) { dc.init(); cin >> n >> m >> s >> t; dc.add(s, s + n, inf); dc.add(t, t + n, inf); for (int i = 1; i <= n; i++) { cin >> a; dc.add(i, i + n, a); } for (int i = 0; i < m; i++) { cin >> a >> b; dc.add(a + n, b, inf); dc.add(b + n, a, inf); } cout << dc.minflow(s, t + n) << endl; } return 0;}
阅读全文
0 0
- HDU 3491 Thieves(经典拆点建图,割点)
- HDU 3491 Thieves 拆点 最小割
- Thieves (hdu 3491 拆点 最小割)
- hdu 3491 Thieves(最小割)
- HDU 3491 Thieves | 最小割
- hdu 3491 Thieves 最小割
- hdoj 3491 Thieves 【最小割 + 拆点】
- HDU 3491 Thieves 【拆点+最大流】
- hdu 3491(最小割+拆点)
- HDU 3491 Thieves 最小点割集+拆点==最大流(建图可贵)
- hdu 3491 Thieves
- hdu 3491 Thieves
- hdu 3491 Thieves
- HDU-3491 Thieves
- hdu 3491 Thieves(最小割拆点)
- 【HDU】3491 Thieves 最小点割集
- Thieves----简单最小割
- Thieves HDU
- redis基本操作
- ubantu下载与安装(virtualBox)
- 欢迎使用CSDN-markdown编辑器
- xml相关知识简介
- 2017年暑假集训总结
- HDU 3491 Thieves(经典拆点建图,割点)
- 机器学习(1)-K-近邻算法(KNN)
- npm查看全局安装过的包
- python的类
- Spring BeanDefinitionStoreException
- The Google File System : part3 SYSTEM INTERACTIONS
- 为什么要开始学会投资理财了
- c++ gdb调试大全
- 一个优秀的Android应用从建项目开始