BZOJ3438 小M的作物

我以为是最大权闭合子图来着。然后好像就直接最小割就行了吧。突然觉得我的网络流好弱。

 

建源汇,分别连每个作物。对于每个组合建两个点分别边源汇,然后中间像源汇一样连它的成员。如果全在一边,那么会有一条边不用割。这也是一个集合都选对答案有贡献的建图方式。

 

然后就完了。建图和dinic都写得有些丑,所以调了半天。

 

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

struct edge {
	int t, c;
	edge *next, *rv;
};

const int maxn = 3009;
const int inf = 0x3f3f3f3f;

int n, m, c, d[maxn], t, st, te;
edge *head[maxn];

inline edge* newEdge(int u, int v, int c) {
	edge* e(new edge);
	e-> t = v;
	e-> c = c;
	e-> next = head[u];
	return head[u] = e;
}
inline void addEdge(int u, int v, int c) {
	edge *a(newEdge(u, v, c)), *b(newEdge(v, u, 0));
	a-> rv = b;
	b-> rv = a;
}

bool bfsBuild() {
	static int q[maxn];
	int hd(0), tl(1);
	memset(d, 0, sizeof(d));
	d[q[0] = st] = 1;
	while (hd < tl && !d[te]) {
		int p(q[hd ++]);
		for (edge* e = head[p]; e; e = e-> next)
			if (e-> c && !d[e-> t]) {
				d[e-> t] = d[p] + 1;
				q[tl ++] = e-> t;
			}
	}
	return d[te];
}
int dfsFind(int p, int c) {
	if (p == te)
		return c;
	int s(0);
	edge *e;
	for (e = head[p]; e && c; e = e-> next)
		if (e-> c && d[e-> t] == d[p] + 1) {
			int x(dfsFind(e-> t, min(c, e-> c)));
			s += x;
			c -= x;
			e-> c -= x;
			e-> rv-> c += x;
		}
	if (!e)
		d[p] = 0;
	return s;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	c = 0;
	scanf("%d", &n);
	st = n;
	te = n + 1;
	c = n + 2;
	t = 0;
	memset(head, 0, sizeof(head));
	for (int i = 0; i < n; ++ i) {
		int a;
		scanf("%d", &a);
		t += a;
		addEdge(st, i, a);
	}
	for (int i = 0; i < n; ++ i) {
		int a;
		scanf("%d", &a);
		t += a;
		addEdge(i, te, a);
	}
	scanf("%d", &m);
	for (int i = 0; i < m; ++ i) {
		int k, c1, c2, u, v;
		scanf("%d%d%d", &k, &c1, &c2);
		t += c1 + c2;
		u = c ++;
		v = c ++;
		addEdge(st, u, c1);
		addEdge(v, te, c2);
		for (int i = 0; i < k; ++ i) {
			int x;
			scanf("%d", &x);
			-- x;
			addEdge(u, x, inf);
			addEdge(x, v, inf);
		}
	}
	while (bfsBuild())
		t -= dfsFind(st, inf);
	printf("%d\n", t);
}

BZOJ1822 [JSOI2010]Frozen Nova 冷冻波

简单的算几+网络流么。然后花了将近两天。最近总和算几过不去啊。

 

判断线段和圆是否有交还是比较简单的。反正不要让我用解析。先找下垂线,然后找下垂足,然后点乘一下搞定。然后错得不知道怎么死的。搞了很久。

 

然后二分网络流水水水水水水水水。

 

感觉mac好卡啊,gdb巨卡,bash也非常卡。难道我又没有搞对打开方式?

 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;

inline long double sqr(long double x) {
	return x * x;
}

typedef struct geo_obj {
	double x, y;
	geo_obj() {}
	geo_obj(double x0, double y0) {
		x = x0, y = y0;
	}
	inline void read() {
		scanf("%lf%lf", &x, &y);
	}
	inline geo_obj rev() {
		return geo_obj(-y, x);
	}
	inline double len() {
		return sqrt(sqr(x) + sqr(y));
	}
	inline double sqLen() {
		return sqr(x) + sqr(y);
	}
} point, vect;
inline geo_obj operator +(const geo_obj& a, const geo_obj& b) {
	return geo_obj(a. x + b. x, a. y + b. y);
}
inline geo_obj operator -(const geo_obj& a, const geo_obj& b) {
	return geo_obj(a. x - b. x, a. y - b. y);
}
inline geo_obj operator *(const geo_obj& a, const double& b) {
	return geo_obj(a. x * b, a. y * b);
}
inline double operator *(const geo_obj& a, const geo_obj& b) {
	return a. x * b. y - a. y * b. x;
}
inline double operator &(const geo_obj& a, const geo_obj& b) {
	return a. x * b. x + a. y * b. y;
}

struct line {
	point p;
	vect v;
	line(point a, point b) {
		p = a;
		v = b - a;
	}
};
struct circle {
	point o;
	double r;
	void read() {
		o. read();
		scanf("%lf", &r);
	}
};

inline point lineCross(const line& a, const line& b) {
	vect w(b. p - a. p);
	double rat((w * a. v) / (a. v * b. v));
	return b. p + b. v * rat;
}

bool segInCircle(point a, point b, circle c) {
	line l(a, b);
	vect u(l. v. rev());
	line r(c. o, c. o + u);
	point p(lineCross(l, r));
	double x = (p - c. o). sqLen();
	double sr(sqr(c. r));
	if (x >= sr)
		return 0;
	if (((a - p) & (b - p)) <= 0)
		return 1;
	if ((a - c. o). sqLen() <= sr)
		return 1;
	if ((b - c. o). sqLen() <= sr)
		return 1;
	return 0;
}

struct edge {
	int t, c;
	edge *next, *rv;
};

struct wiz {
	point p;
	int r, t;
	void read() {
		p. read();
		scanf("%d%d", &r, &t);
	}
};

const int maxn = 409;
const int maxe = 80409;
const int inf = 0x3f3f3f3f;

int n, m, c, t, ea[maxe], eb[maxe], ou[maxn];
int d[maxn], st, te;
wiz w[maxn];
circle tree[maxn];
point spi[maxn];
edge elst[maxe], *ep, *head[maxn << 1];

inline edge* newEdge(int u, int v, int c) {
	ep-> t = v;
	ep-> c = c;
	ep-> next = head[u];
	head[u] = ep;
	return ep ++;
}
inline void addEdge(int u, int v, int c) {
	edge *a = newEdge(u, v, c);
	edge *b = newEdge(v, u, 0);
	a-> rv = b;
	b-> rv = a;
}

bool bfsBuild() {
	static int q[maxn];
	int hd(0), tl(1);
	memset(d, 0, sizeof(d));
	d[q[0] = st] = 1;
	while (hd < tl && !d[te]) {
		int p(q[hd ++]);
		for (edge* e = head[p]; e; e = e-> next)
			if (e-> c && !d[e-> t]) {
				d[e-> t] = d[p] + 1;
				q[tl ++] = e-> t;
			}
	}
	return d[te];
}
int dfsFind(int p, int c) {
	if (p == te)
		return c;
	int s(0);
	edge* e;
	for (e = head[p]; e && c; e = e-> next)
		if (e-> c && d[e-> t] == d[p] + 1) {
			int x(dfsFind(e-> t, min(e-> c, c)));
			s += x;
			c -= x;
			e-> c -= x;
			e-> rv-> c += x;
		}
	if (!e)
		d[p] = -1;
	return s;
}

int binSearch() {
	int l(0), r(5000000);
	st = n + m;
	te = st + 1;
	while (l < r) {
		int mid((l + r) >> 1);
		ep = elst;
		memset(head, 0, sizeof(head));
		for (int i = 0; i < t; ++ i)
			addEdge(ea[i], eb[i] + n, 1);
		for (int i = 0; i < n; ++ i)
			addEdge(st, i, (mid + w[i]. t) / w[i]. t);
		for (int i = 0; i < m; ++ i)
			addEdge(i + n, te, 1);
		int s(0);
		while (bfsBuild())
			s += dfsFind(st, inf);
		if (s == m)
			r = mid;
		else
			l = mid + 1;
	}
	return l;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	scanf("%d%d%d", &n, &m, &c);
	for (int i = 0; i < n; ++ i)
		w[i]. read();
	for (int i = 0; i < m; ++ i)
		spi[i]. read();
	for (int i = 0; i < c; ++ i)
		tree[i]. read();
	memset(ou, 0, sizeof(ou));
	t = 0;
	for (int i = 0; i < n; ++ i)
		for (int j = 0; j < m; ++ j) {
			bool f(1);
			double ds(sqr(w[i]. p. x - spi[j]. x) + sqr(w[i]. p. y - spi[j]. y));
			if (ds > sqr(w[i]. r))
				f = 0;
			for (int k = 0; k < c && f; ++ k)
				if (segInCircle(w[i]. p, spi[j], tree[k]))
					f = 0;
			if (f) {
				ea[t] = i;
				eb[t] = j;
				++ t;
				ou[j] = 1;
			}
		}
	bool hs(1);
	for (int i = 0; i < m && hs; ++ i)
		if (!ou[i])
			hs = 0;
	if (!hs || !n)
		puts("-1");
	else
		printf("%d\n", binSearch());
}