SRM 399

水题,枚举+最大流,数据小连二分都不用


果然前面场次水题多,还是老老实实做最近的那些吧- -


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <queue>

using namespace std;

class DancingParty {
public:
	int maxDances(vector<string> , int);
};
#define N 20009
#define M 2000009
#define inf 2000000000
#define INT int
struct E {
	int t, next;
	INT flow, cap;
} edge[M];
int node[N], eid;
vector<int> e[N];
int rrank[N];
int que[N];
void init() {
	eid = 0;
	memset(rrank, -1, sizeof(rrank));
	memset(node, -1, sizeof(node));
}
void addedge(int a, int b, INT c) {
	edge[eid].t = b;
	edge[eid].cap = c;
	edge[eid].flow = 0;
	edge[eid].next = node[a];
	node[a] = eid++;

	edge[eid].t = a;
	edge[eid].cap = 0; //0单向,c双向
	edge[eid].flow = 0;
	edge[eid].next = node[b];
	node[b] = eid++;
}
void addedge1(int a, int b, INT c) {
	edge[eid].t = b;
	edge[eid].cap = c;
	edge[eid].flow = 0;
	edge[eid].next = node[a];
	node[a] = eid++;

	edge[eid].t = a;
	edge[eid].cap = c; //0单向,c双向
	edge[eid].flow = 0;
	edge[eid].next = node[b];
	node[b] = eid++;
}
int bfs(int s, int t, int n) {
	memset(rrank, -1, sizeof(rrank));
	int i;
	for (i = 0; i < n; ++i)
		e[i].clear();
	int u, v;
	int front = 0, rear = 1;
	rrank[s] = 0;
	que[0] = s;
	while (rear > front) {
		u = que[front++];
		for (i = node[u]; i != -1; i = edge[i].next) {
			v = edge[i].t;
			if (rrank[v] == -1 && edge[i].cap) {
				que[rear++] = v;
				rrank[v] = rrank[u] + 1;
			}
			if (rrank[v] == rrank[u] + 1)
				e[u].push_back(i);
		}
	}
	return (rrank[t] != -1);
}
INT dinic(int s, int t, int n) {
	int st[N];
	INT maxflow = 0;
	int aux[N];
	int top, cur;
	int p, i, k;
	while (bfs(s, t, n)) {
		top = 0;
		st[top] = s;
		cur = s;
		while (1) {
			if (cur == t) {
				INT minc = inf;
				for (i = 0; i < top; ++i) {
					p = aux[i + 1];
					if (minc > edge[p].cap)
						minc = edge[p].cap, k = i;
				}
				for (i = 0; i < top; ++i) {
					p = aux[i + 1];
					edge[p].cap -= minc;
					edge[p ^ 1].cap += minc;
				}
				maxflow += minc;
				cur = st[top = k];
			}
			int len = e[cur].size();
			while (len) {
				p = e[cur][len - 1];
				if (edge[p].cap && rrank[edge[p].t] == rrank[cur] + 1)
					break;
				else {
					len--;
					e[cur].pop_back();
				}
			}
			if (len) {
				cur = st[++top] = edge[p].t;
				aux[top] = p;
			} else {
				if (top == 0)
					break;
				rrank[cur] = -1;
				cur = st[--top];
			}
		}
	}
	return maxflow;
}

int DancingParty::maxDances(vector<string> likes, int k) {
	int s, t;
	int i, j, p;
	int n = likes.size();
	for (p = 1; p <= n; ++p) {
		init();
		s = 6 * n;
		t = 6 * n + 1;
		for (i = 0; i < n; ++i) {
			addedge(s, 3 * i, p);
			addedge(3 * i, 3 * i + 1, inf);
			addedge(3 * i, 3 * i + 2, k);
			addedge(3 * n + 3 * i, t, p);
			addedge(3 * n + 3 * i + 1, 3 * n + 3 * i, inf);
			addedge(3 * n + 3 * i + 2, 3 * n + 3 * i, k);
		}
		for (i = 0; i < n; ++i) {
			for (j = 0; j < n; ++j) {
				if (likes[i][j] == 'Y')
					addedge(3 * i + 1, 3 * n + 3 * j + 1, 1);
				else
					addedge(3 * i + 2, 3 * n + 3 * j + 2, 1);
			}
		}
		if (dinic(s, t, t + 1) != p * n)
			break;
	}
	return p - 1;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值