Dining(最大流-拆点-EK算法-Dinic算法)

Dining(最大流-拆点-EK算法-Dinic算法)

judge:POJ 3281
Time Limit: 2000MS
Memory Limit: 65536K
source:USACO 2007 Open Gold

Description

Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others.……
POJ 3281

Input

POJ 3281

Output

POJ 3281

Sample Input

4 3 3
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3

Sample Output

3

Hint

POJ 3281

题意

有n头牛,f种饮料和d种食物

每头牛都有自己想要的饮料和食物(一种或好几种),但是每一种饮料和食物只能被一头牛选择,问你最大能满足多少头牛的要求。

最开始想的是分别对饮料和食物与牛进行最大匹配,但是为了让饮料和食物也能对应上,于是我想到了这样建图:先把饮料与源点相连,再把饮料与牛相连,再把牛与食物相连,最后把食物和汇点相连。这样求最大匹配就OK了。
在这里插入图片描述
后来发现这样做有BUG,因为每头牛只能选一种饮料和一种食物,而不给牛加限制的话就会出现这种情况:在这里插入图片描述

所以为了限制奶牛的流量,故对奶牛进行拆点:拆成前后两部分,前一部分与饮料相连,后一部分与食物相连,并且对每一条边的容量设置成1,于是就不会溢出了。在这里插入图片描述
至于每个点的编号,这个就看个人喜好吧,只要任何两个点的编号不重复就OK。

由于本人也是初学者,所以分别用两种算法分别实现了一下。下面给出两种算法的代码

EK算法版(结构较简单,适用于简单的网络流)
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#define _for(i, a) for(int i = 0; i < (a); i++)
#define _rep(i, a, b) for(int i = (a); i <= (b); i++)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 10005;
using namespace std;

struct poi {
	int u, v, cap, next;//w 0 drinks	1 vegetable
}edges[maxn];

int head[maxn], cnt;
int n, f, d;
int dis[maxn];
int S, T;
int p[maxn];

void init() {
	memset(head, -1, sizeof(head));
	memset(edges, 0, sizeof(edges));
	cnt = 0;
	S = 2 * n + f + d + 1;
	T = S + 1;
}

void adde(int u, int v, int w) {
	edges[cnt].u = u, edges[cnt].v = v, edges[cnt].cap = w;
	edges[cnt].next = head[u], head[u] = cnt++;
	edges[cnt].u = v, edges[cnt].v = u, edges[cnt].cap = 0;
	edges[cnt].next = head[v], head[v] = cnt++;
}

int EK() {
	int flow = 0;
	while (1) {
		memset(dis, 0, sizeof(dis));
		queue<int> Q;
		Q.push(S);
		dis[S] = inf;
		while (!Q.empty()) {
			int u = Q.front();
			Q.pop();
			for (int i = head[u]; ~i; i = edges[i].next) {
				int v = edges[i].v, cap = edges[i].cap;
				if (!dis[v] && cap > 0) {
					p[v] = i;
					dis[v] = min(dis[u], cap);
					Q.push(v);
				}
			}
			if (dis[T]) break;
		}
		if (!dis[T]) break;
		for (int u = T; u != S; u = edges[p[u]].u) {
			edges[p[u]].cap -= dis[T];
			edges[p[u] ^ 1].cap += dis[T];
		}
		flow += dis[T];
	}
	return flow;
}

int main() {
	//freopen("in.txt", "r", stdin);
	ios::sync_with_stdio(false);
	while (cin >> n >> f >> d) {
		init();
		_rep(i, 2 * n + 1, 2 * n + f) {
			adde(S, i, 1);
		}
		_rep(i, 1, n) {
			adde(i, i + n, 1);
		}
		_rep(i, 2 * n + f + 1, 2 * n + f + d) {
			adde(i, T, 1);
		}
		_rep(i, 1, n) {
			int fi, di;
			cin >> fi >> di;
			_rep(j, 1, fi) {
				int v;
				cin >> v;
				adde(v + 2 * n, i, 1);
			}
			_rep(j, 1, di) {
				int v;
				cin >> v;
				adde(i + n, v + 2 * n + f, 1);
			}
		}
		printf("%d\n", EK());
	}
	return 0;
}

Dinic算法版(结构较复杂,适用性强)
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#define _for(i, a) for(int i = 0; i < (a); i++)
#define _rep(i, a, b) for(int i = (a); i <= (b); i++)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 10005;
using namespace std;

struct poi {
	int u, v, cap, next;//w 0 drinks	1 vegetable
}edges[maxn];

int head[maxn], cnt;
int n, f, d;
int dis[maxn];
int S, T;
int cur[maxn];

void init() {
	memset(head, -1, sizeof(head));
	memset(edges, 0, sizeof(edges));
	cnt = 0;
	S = 2 * n + f + d + 1;
	T = S + 1;
}

void adde(int u, int v, int w) {
	edges[cnt].u = u, edges[cnt].v = v, edges[cnt].cap = w;
	edges[cnt].next = head[u], head[u] = cnt++;
	edges[cnt].u = v, edges[cnt].v = u, edges[cnt].cap = 0;
	edges[cnt].next = head[v], head[v] = cnt++;
}

//bfs 分层次
bool bfs() {
	memset(dis, 0, sizeof(dis));
	dis[S] = 1;
	queue<int> Q;
	Q.push(S);
	int flow = 0;
	while (!Q.empty()) {
		int u = Q.front();
		Q.pop();
		for (int i = head[u]; ~i; i = edges[i].next) {
			int v = edges[i].v, cap = edges[i].cap;
			if (cap > 0 && !dis[v]) {
				dis[v] = dis[u] + 1;
				Q.push(v);
			}
		}
	}
	return dis[T] != 0;
}

//dfs 找增广路
int dfs(int u, int mw) {
	if (u == T || mw == 0) return mw;
	int flow = 0;
	for (int &i = cur[u]; ~i; i = edges[i].next) {//从上次考虑的弧开始
		int v = edges[i].v, cap = edges[i].cap;
		if (cap > 0 && dis[v] == dis[u] + 1) {
			int cw = dfs(v, min(mw, cap));
			flow += cw;
			edges[i].cap -= cw;
			edges[i ^ 1].cap += cw;
			mw -= cw;
			if (mw == 0) break;
		}
	}
	return flow;
}

//主进程
int dinic() {
	int res = 0;
	while (bfs()) {
		memcpy(cur, head, sizeof(head));
		res += dfs(S, inf);
	}
	return res;
}

int main() {
	//freopen("in.txt", "r", stdin);
	ios::sync_with_stdio(false);
	while (cin >> n >> f >> d) {
		init();
		_rep(i, 2 * n + 1, 2 * n + f) {
			adde(S, i, 1);
		}
		_rep(i, 1, n) {
			adde(i, i + n, 1);
		}
		_rep(i, 2 * n + f + 1, 2 * n + f + d) {
			adde(i, T, 1);
		}
		_rep(i, 1, n) {
			int fi, di;
			cin >> fi >> di;
			_rep(j, 1, fi) {
				int v;
				cin >> v;
				adde(v + 2 * n, i, 1);
			}
			_rep(j, 1, di) {
				int v;
				cin >> v;
				adde(i + n, v + 2 * n + f, 1);
			}
		}
		printf("%d\n", dinic());
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
R-CNN源代码是一个基于深度学习的目标检测算法,用于识别图像中的物体。下面是R-CNN的Python源代码示例: ```python import cv2 import numpy as np import matplotlib.pyplot as plt # Load the input image image = cv2.imread('input_image.jpg') # Load the pre-trained network for object detection net = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'model.caffemodel') # Define the class labels class_labels = ['background', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor'] # Create a blob from the input image blob = cv2.dnn.blobFromImage(image, size=(300, 300), swapRB=True) # Set the input to the network net.setInput(blob) # Run the forward pass to get the output of the model detections = net.forward() # Loop over the detections for i in range(detections.shape[2]): confidence = detections[0, 0, i, 2] # Check if the detection has a high enough confidence if confidence > 0.5: class_id = int(detections[0, 0, i, 1]) # Get the coordinates of the bounding box box = detections[0, 0, i, 3:7] * np.array([image.shape[1], image.shape[0], image.shape[1], image.shape[0]]) x1, y1, x2, y2 = box.astype('int') # Draw the bounding box and class label cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), thickness=2) cv2.putText(image, class_labels[class_id], (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, fontScale=0.5, color=(0, 255, 0), thickness=2) # Show the output image plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) plt.show() ``` 该代码使用OpenCV和Caffe实现了R-CNN目标检测算法。在这个代码示例中,我们首先加载输入图像,然后加载预先训练好的网络模型。我们创建一个blob对象,然后将其输入到网络中进行前向传递,并获得模型的输出结果。最后,我们遍历输出结果,将置信度高于0.5的检测框绘制在图像上,并标注检测到的物体的类别。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值