hdu4289 Control最小割

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">一个城市交通图,上面有n个城市,m条双通道路,现在有个间谍要从s逃到t去,想要抓住他,但是只能在城市里面抓,不能在公路上,通过监控城市来实现抓捕,监控每个城市需要一定的费用,只要在所监控的城市出现了这个间谍就能抓住他,问抓住间谍的最小费用。</span>

就是不能让间谍到达t,可以转换成s到t的最小割,将城市拆点,容量为监控费用。

/*****************************************
Author      :Crazy_AC(JamesQi)
Time        :2016
File Name   :最小割==最大流。
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 500;
const int maxm = 100000;
int head[maxn], cap[maxm], flow[maxm], pnt[maxm], nxt[maxm];
int ecnt;
inline void Addedge(int u,int v,int c) {
	pnt[ecnt] = v, nxt[ecnt] = head[u], cap[ecnt] = c;
	flow[ecnt] = 0, head[u] = ecnt++;

	pnt[ecnt] = u, nxt[ecnt] = head[v], cap[ecnt] = 0;
	flow[ecnt] = 0, head[v] = ecnt++;
}
int s, t;
int dis[maxn];
bool spfa() {
	queue<int> que;
	memset(dis, -1,sizeof dis);
	dis[s] = 0;
	que.push(s);
	while(!que.empty()) {
		int u = que.front();
		que.pop();
		// cout << u << ' ';
		for (int i = head[u];i != -1;i = nxt[i]) {
			int v = pnt[i];
			if (cap[i] > flow[i] && dis[v] == -1) {
				dis[v] = dis[u] + 1;
				que.push(v);
			}
		}
	}
	// cout << endl;
	return dis[t] != -1;
}
int dfs(int u,int a) {
	if (u == t || a == 0) return a;
	int ret = 0,f;
	for (int i = head[u];i != -1;i = nxt[i]) {
		int v = pnt[i];
		if (dis[v] > dis[u] && (f = dfs(v, min(a, cap[i] - flow[i]))) > 0) {
			ret += f;
			a -= f;
			flow[i] += f;
			flow[i^1] -= f;
			if (a == 0) break;
		}
	}
	return ret;
}
int MaxFlow() {
	int ret = 0;
	while(spfa()) {
		// cout << "here\n";
		ret += dfs(s, INF);
	}
	return ret;
}
int n, m;
int main()
{	
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	while(~scanf("%d%d",&n,&m)) {
		s = 0,t = n*2 + 1;
		int u, v, c;

		scanf("%d%d",&u,&v);

		memset(head, -1,sizeof head);
		ecnt = 0;

		Addedge(s, u, INF);
		Addedge(v + n, t, INF);

		for (int i = 1;i <= n;++i) {
			scanf("%d",&c);
			Addedge(i,i+n,c);
		}
		for (int i = 1;i <= m;++i) {
			scanf("%d%d",&u,&v);
			Addedge(u+n, v, INF);
			Addedge(v+n, u, INF);
		}
		printf("%d\n", MaxFlow());
	}
	return 0;
}

/*****************************************
Author      :Crazy_AC(JamesQi)
Time        :2016
File Name   :ISAP
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 500;
struct Edge{
	int from, to, cap, flow;
	Edge(){}
	Edge(int from,int to,int cap,int flow)
		:from(from),to(to),cap(cap),flow(flow){ }
};
struct ISAP{
	int n, m, s, t;

	bool vis[maxn];
	int cur[maxn], num[maxn], dis[maxn], pre[maxn];

	vector<Edge>edges;
	vector<int>G[maxn];

	void init(int n) {
		this->n = n;
		for (int i = 0;i <= n;++i) {
			G[i].clear();
			dis[i] = INF;
		}
		edges.clear();
	}

	void addedge(int u,int v,int c) {
		edges.push_back(Edge(u, v, c, 0));
		edges.push_back(Edge(v, u, 0, 0));
		m = (int)edges.size();
		G[u].push_back(m-2);
		G[v].push_back(m-1);
	}

	bool bfs() {
		memset(vis, false,sizeof vis);
		queue<int> que;
		que.push(t);
		dis[t] = 0;
		vis[t] = true;
		while(!que.empty()) {
			int u = que.front();
			que.pop();

			for (int i = 0;i < G[u].size();++i) {
				Edge& e = edges[G[u][i]^1];
				if (e.cap > e.flow && !vis[e.from]) {
					vis[e.from] = true;
					dis[e.from] = dis[u] + 1;
					que.push(e.from);
				}
			}
		}
		return vis[s];
	}

	int Augment() {
		int u = t, flow = INF;
		while(u != s) {
			Edge& e = edges[pre[u]];
			flow = min(flow, e.cap - e.flow);
			u = edges[pre[u]].from;
		}

		u = t;
		while(u != s) {
			edges[pre[u]].flow += flow;
			edges[pre[u]^1].flow -= flow;
			u = edges[pre[u]].from;
		}
		return flow;
	}

	int MaxFlow(int s,int t) {
		this->s = s, this->t = t;
		int ret = 0;
		bfs();
		if (dis[s] >= n) return 0;
		memset(num, 0,sizeof num);
		memset(cur, 0,sizeof cur);
		for (int i = 0;i < n;++i) {
			if (dis[i] < INF) num[dis[i]]++;
		}
		int u = s;

		while(dis[s] < n) {

			if (u == t) {
				ret += Augment();
				u = s;
			}

			bool ok = false;

			for (int i = cur[u];i < G[u].size();++i) {
				Edge& e = edges[G[u][i]];
				if (e.cap > e.flow && dis[u] == dis[e.to] + 1) {
					ok = true;
					pre[e.to] = G[u][i];
					cur[u] = i;
					u = e.to;
					break;
				}
			}

			if (!ok) {
				int Min = n - 1;
				for (int i = 0;i < G[u].size();++i) {
					Edge& e = edges[G[u][i]];
					if (e.cap > e.flow ) Min = min(Min, dis[e.to]);
				}
				if (--num[dis[u]] == 0) break;
				num[dis[u] = Min + 1]++;
				cur[u] = 0;
				if (u != s) u = edges[pre[u]].from;
			}
		}
		return ret;
	}
};
ISAP isap;
int n, m;
int s, t;
int main()
{	
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	while(~scanf("%d%d",&n,&m)) {
		s = 0,t = n * 2 + 1;
		isap.init(t+1);

		int u, v, c;
		scanf("%d%d",&u,&v);
		isap.addedge(s, u, INF);
		isap.addedge(v + n, t, INF);
		for (int i = 1;i <= n;++i) {
			scanf("%d",&c);
			isap.addedge(i,i+n,c);
		}
		for (int i = 1;i <= m;++i) {
			scanf("%d%d",&u,&v);
			isap.addedge(u+n,v,INF);
			isap.addedge(v+n,u,INF);
		}
		printf("%d\n", isap.MaxFlow(s, t));
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值